How do I force Craft to regenerate assets transform? I had to add an image size in the assets transforms; all my pics were previously uploaded, but when I use getUrl('headIpad'), it makes urls like this:

http://host.com/cpresources/transforms/4/

Instead of this:

http://host.com/uploads/team-photo/_headIpad/fall-back.jpg

I tried to use generateTransformsBeforePageLoad in my config but Craft generates an error:

  Internal Server Error
  Image “fall-back.jpg” cannot be found.

Any ideas?

If you simply go into your craft_assettransformindex table and empty it, that should trigger brand new transformations for everything.


Importing members from EE without password reset We've rewritten an EE site on Craft and now need to import the members.

My understanding is that since passwords are hashed & not encrypted there is no way to transfer the passwords from EE to Craft without having to force members to reset their passwords.

Is that correct ?

It would be possible to write a plugin that provides an alternative login controller action, based on UsersController::actionLogin(). The difference would be that, if normal login fails, it could try checking the old ExpressionEngine database to see if the user exists there, and if so, it could hash up the password in the same way EE does it, and see if it matches. When a password matches, the plugin could then A) update the user's password in the Craft database, and B) log the user in.

The only caveat (besides that this is a bit of work) is that it will only work for front-end login forms; you can’t change where the CP login form is submitted to.

So, your plugin would need a custom controller class, with the following code:

namespace Craft;

class CustomLoginController extends BaseController
{
    protected $allowAnonymous = true;

    public function actionLogin()
    {
        // Attempt to log the user in
        $this->_login();

        // Now pass back to the normal login controller
        craft()->runController('users/login');
    }

    private function _login()
    {
        if (craft()->userSession->isLoggedIn())
        {
            return;
        }

        if (craft()->request->isPostRequest())
        {
            $loginName = craft()->request->getPost('loginName');
            $password = craft()->request->getPost('password');
            $rememberMe = (bool) craft()->request->getPost('rememberMe');

            // Try logging them in normally
            if (craft()->userSession->login($loginName, $password, $rememberMe))
            {
                return;
            }

            // Is it an actual user account, at least?
            $user = craft()->users->getUserByUsernameOrEmail($loginName);

            if ($user)
            {
                // See if they had an EE user account
                $host = craft()->config->get('server', ConfigFile::Db);
                $port = craft()->config->get('port', ConfigFile::Db);
                $dbName = 'ee_database_name';
                $dbUser = 'ee_database_username';
                $dbPass = 'ee_database_password';
                $db = new DbConnection('mysql:host='.$host.';dbname='.$dbName.';port='.$port.';', $dbUser, $dbPass);

                $row = $db->createCommand()
                    ->select('member_id, password, salt')
                    ->from('exp_members')
                    ->where(array('or', 'username=:login', 'email=:login'), array(':login' => $loginName))
                    ->queryRow();

                if ($row)
                {
                    $hashedPassword = $this->_hashEEPassword($password);

                    if ($hashedPassword == $row['password'])
                    {
                        // Eureka! Now update the local user account
                        $user->newPassword = $password;
                        craft()->users->changePassword($user);

                        // Delete the old user row so their old password stops working
                        $db->createCommand()->delete('exp_members',
                            array('member_id=:id'),
                            array(':id' => $row['member_id']));
                    }
                }
            }
        }
    }

    private function _hashEEPassword($password)
    {
        // Hash the password using EE's hashing technique
        // ...

        return $hashedPassword;
    }
}

The actual code that would go into _hashEEPassword() depends on your EE version. In EE 3.1 it lives in system/ee/legacy/libraries/Auth.php, function hash_password(). Not going to repost it here as it is copyrighted, though.

With the plugin in place and installed, you can start pointing front-end login forms to the new controller action by changing the action hidden input value:

<input type="hidden" name="action" value="customLogin/login">


Is it possible to target a fieldtype by it's Type name, rather than the handle name? I've created an Asset Source and assigned my own field via the field layout.

Then, I created an Assets Field to display a single image on a page. Using my plugins twig extension I can query the image object like so:

{{ entry.featuredImage.first()|myTwigExt }}

Now, in the Twig extension I want to target the first instance of my field using its Type, not the Handle.

The reason for this is because the handle can be defined by the user, but the type name is always the same. I want to avoid the need to parse in the field handle along with the Twig Extension like this:

{{ entry.featuredImage.first()|myTwigExt('notThis') }}

If this is even possible, my ideal situation would have my Twig Extension looking something like this:

  public function getFilters() {
    return array(
      'myTwigExt' => new Twig_Filter_Method($this, 'myTwigExtension'),
    );
  }

  public function myTwigExtension($image, $param) {
   if ( $image->type('myCustomField') ) {
     // YAY!
     return $image->type('myCustomField')->someDataFromMyField;
   }

   if ( $image->$param ) {
     // "Boo!";
     return $image->$param->someDataFromMyField;
   }
  }

This is the cleanest way I can ask this question. Without going into too much detail about my plugin (which would just confuse the situation more).

I am not sure if I am understanding your question correctly, so here is my understanding before I give my solution:

You want to be able to access a field on an asset by it's field type rather than it's handle.

Given this understanding, here is my solution:

I have not been able to accomplish this using Craft relations. However, you can loop through the fields attached to the asset, and check their type. It is a little bit confusing as Craft stores the data for fields and field layouts across several tables.

An element has a field layout (FieldLayoutModel), and the layout then has fields (FieldLayoutFieldModels). Then each of those FieldLayoutFieldModels has fields (FieldModel) which are the actual fields we are looking for. Putting this together, we can loop through and check the field type like so:

    // get the fieldLayoutModel
    $fieldLayoutModel = $image->fieldLayout;

    // get array of FieldLayoutFieldModel
    $fieldLayoutFields = $fieldLayoutModel->fields;

    foreach($fieldLayoutFields as $fieldLayoutField){

        // get the field associated with the layout
        $field = $fieldLayoutField->field;
        if($field->type == 'myFieldType'){
            // do whatever
            break;
        }
    }

Hopefully this is what you were looking for!


Simple search using a single category in Craft CMS I am relatively new to Craft and I am having a little trouble understanding how to build a simple search which will allow me to have dropdown of my categories which will return the selected category and return results on /products/results page.

I have a category called "Products" and have the following categories "Fruit", "Vegetables", "Dairy", "Herbs", "Eggs", and "Misc".  I would like to have these categories in a dropdown menu which would allow visitor to select the category they would like to view.  I also need it to show all product when they select "All Products", with "All Products" being the default value.

Thank you for your help.

You can build you categories dropdown using the craft.categories tag.  Your Form submission field will end up looking something like this in HTML:

<form action="search/results" method="get">
    <select name="querySlug">
      <option value="*">All products</option>
      <option value="fruit">Fruit</option>
      <option value="vegetables">Vegetables</option>
      <option value="dairy">Dairy</option>
    </select>
    <input type="submit" value="Search">
</form>

Your results page will behave similar to the example results page in the Craft docs, except, instead of passing your query to a craft.entries.search() tag, you'll want to pass it to the craft.categories.slug() tag and then hand off the CategoryModel you get back to the craft.entries tag using relatedTo():

{% set querySlug = craft.request.getParam('querySlug') %}
{% set category = craft.categories.group('productCategories').slug(querySlug) %}
{% set entries = craft.entries.section('products').relatedTo(category) %}

All categories are returned by default, so you just have to handle that in a conditional if somebody selects that option.  Here is a simple way you could do that:

{% set querySlug = craft.request.getParam('querySlug') %}
{% set category = craft.categories.group('productCategories').slug(querySlug) %}

{% if querySlug == "*" %}
    {% set products = craft.entries.section('products') %}
{% else %}
    {% set products = craft.entries.section('products').relatedTo(category) %}
{% endif %}


What is the correct method for getting a client to purchase a Craft license? What is the recommended way from P&T to get a client to purchase a license for Craft CMS? It doesn't actually say how on the website.

If you give a user literally all the permissions Craft has, when they log in to an unlicensed Craft Pro install, they'll see this warning at the top:

If they click Resolve, they get taken to /admin/plugin-store/upgrade-craft and see this error:

The only way I can see for a client to purchase a license is to make them a full Admin, which goes against everything the permissions are set up for. I don't ever want to make a client a full site administrator because they can easily break stuff.

Context: I'm working on behalf of a larger design agency, and the end client is liable for purchasing their own licenses. The design agency is not buying it on their behalf.

I normally pay for the license and bill back to the client, turning off automatic renewal. After purchasing, if the client wants to have access to their license, I have them create a Craft ID account and transfer the license to them.


Need to create dynamic CSS names for buttons This may not be the most efficient approach for this specific case but I'm trying to learn how this might be done for other similar problems I might run across in the future so bear with me here.

I have a Global that creates links to social media sites on my profile page. My fields include icon (asset), name (text), url (text), and color (color). I have included the following at the top of my template:

{% set buttonCSS %}
    {% for block in contactLinks.contactLinks.type("contactLink") %}
    .{{ block.contactLinkName | lower }}:hover {
        background-color: {{ block.buttonColor }}
    }
    {% endfor %}
{% endset %}

{% includeCss buttonCSS %}

This generates dynamic styles for each button at the top of my profile page so I can add links. My template then generates the links:

{% for block in contactLinks.contactLinks.type("contactLink") %}

{{ block.contactLinkName }}

{% endfor %}

Now, for the most part this works since social media sites tend to be one word but when I tried to use "Let's Talk" for my email link I run into problems with the CSS. What's the best way to strip the apostrophe and spaces from my class names?

I would use the slugify twig filter:

{{ block.contactLinkName | slugify }}

It will handle apostrophies, spaces, and anything else that might come along.


List both parent entry and its child entry I am trying to display a list of entries.  Specifically the parent entry and it's children's entry.

I started off using this:

{% nav page in craft.entries.section('forms').isChildOf.slug('applicant-form') %}

        {{ page.getLink() }}

        {% ifchildren %}

{% children %}

        {% endifchildren %}

{% endnav %}

But this only displays the Parent.

I found this solution on Stack here, and all the children display but not the parent.  I also wonder if this is the best solution to display the children as it seems a bit more lines than what is in the Craft docs.

Many thanks.

{% set topLevel = (entry.level == 1) ? entry : entry.getAncestors().level(1).first()  %}

{% if topLevel.hasDescendants %}

        {% set nav =  topLevel.getDescendants()  %}

        {% nav page in nav  %}
            {% if page.id != entry.id %}

{{ page.getLink() }}

            {%else%}

{{page}}

            {%endif%}

        {% ifchildren %}

                {% children %}

        {% endifchildren %}

        {% endnav %}

{% endif %}

This is the corrected Twig code. I simply added {{ entry.title }} as an
 item. This nav appears only on the page that I needed entry.title displaying.

{% set navList = (entry.level == 2) ? entry : entry.getAncestors().level(2).first()  %}

{% if navList.hasDescendants %}

        {% set nav =  navList.getDescendants()  %}

{{ entry.title }}

        {% nav page in nav  %}
            {% if page.id != entry.id %}

{{ page.getLink() }}

            {% else %}

{{page}}

            {% endif %}
        {% ifchildren %}

                {% children %}

        {% endifchildren %}
        {% endnav %}

{% endif %}


Is there a way to add custom aspect ratios in the image editor? We'd like to add a custom aspect ratio to the list of aspect aspect ratios in the image editor so our client doesn't have to look it up to remember each time. Is this possible?

This will be possible using a new imageEditorRatios config setting that is coming in Craft 3.5 (due to release in early August 2020):
...
'imageEditorRatios' => [
    'Unconstrained' => 'none',
    'Original' => 'original',
    'Square' => 1,
    '16:9' => 1.78,
    '10:8' => 1.25,
    '7:5' => 1.4,
    '4:3' => 1.33,
    '5:3' => 1.67,
    '3:2' => 1.5,
    'Some custom ratio' => 1.9,
];

Source (GitHub issue)


Craft Commerce Order Notifications from customer email and name Quite a specific question from a client on another e-commerce system who would maybe like to move to Craft Commerce. I have used Craft for a few client sites now but not Commerce as of yet.

Basically, when a customer places an order he wants the FROM email address and FROM name to be that of the customer who has placed the order (in the confirmation/notification email/invoice that gets sent to him).  It's basically so that he can group all the emails easily in Outlook.

Bit of a specific question but wondered if anyone can shed any light?

You'd need to write a small plugin that listened to Commerce's EVENT_BEFORE_SEND_MAIL event, so you could override the from address of the email to the customer's order.


Set base 'shop' URL to something else in Commerce I am completely new to Craft and to be honest, really struggling to get my head around how it all works at the moment.

I've got loads of, what I feel, is quite basic questions that should be relatively straight forward but after searching numerous documentation and online posts, can't find out how to do any of it.

So figured asking here might be the quickest way of learning how to work with the platform.

So in a development environment, I've got Craft CMS set up with the Pro version of Commerce. By default, this comes set up at /shop/.

What do I have to do exactly in order to change the 'shop' URL to something else, for example /store/?

I tried duplicating the 'shop' directory as 'store' and whilst the pages seem to load at /store/, the templates are still being served from /shop/ (tested by modifying them).

If someone could list step by step the correct process for changing this, that would be very helpful.

The way the demo templates are set up they are a series of included sub-templates.
So you would need to change the references to shop/ for each of the {% include %} statements.

Try doing a find/replace on the templates within your /store directory. See what that does.

Craft/Commerce places no restriction on how you name things. You don't need to use the demo templates at all if you don't want to. You can name them and place them wherever you like.


Sending E-Mails via SMTP with email address that contains special characters I got a problem with some smtp settings in my craft 3.5.14. The domain of my client uses special characters like (ö, ä, ü) and therefore for their email addresses. In this case my client only use the character "ö". When using those email addresses for authentication I always get an error when testing it in craft (settings/email). I can't find anything in the logs. Is it generally possible to send emails with special characters in their domain? Something to watch out for? I also tried to convert the email address into ace through an idn converter. No success. When using another provider on another domain without special characters the sending of emails works. Thx for you help!

After endless try and error I finally got it work. I used the ACE version of the email address e.g.
client@clientwithö.de -> client@xn--clientwith-ncb.de

Although I tried this at the beginning it is working now and I do not know what changed the result. :)


Is it possible to change the title of "Quick Post" dashboard widgets? For this particular build the client will frequently be creating 3 similar, but unique, types of content all housed in the same section which differ by a Content Type. When creating "quick post" widgets for the dashboard, each widget is currently given the same name despite the corresponding Entry Type. I don't necessarily need granular control over the title, but a way to provide additional context to the administrators would be nice.

You can use this Control Panel JS plugin to change the info.

Just copy the cpjs folder in the craft/plugins/ folder and the plugin should appear in Settings->Plugins. Install it and add your code in the textarea displayed at the bottom.

Now with your title:

In the dashboard, each widget has an ID like widget1, widget2, etc; get it with the dev tools.

Then try the following code changing the corresponding widget number:

document.getElementById("widget1").childNodes[3].innerHTML = "new_title";


Update entry.body from Plugin I'd like to run the entry.body content through some PHP functions before the template outputs it, there probably two approaches to this:

Create a twig function via Plug (if possible) and use that in template like:

{{ MyFunction( entry.body ) }}

Have function automatically grab the "body" of the current page, run through functions, and update it before template runs it. I'd prefer this method although but have no clue how to go about it.

What would be the best approach -- and does anyone have any pointers / samples on how it'd be done? I've been digging through documentation but am struggling to find how to get the current entry.body through a plugin, or how to update it (just for the page rendering + template, not in database.)

There is no event or hook that I'm aware of that can intercept the template rendering process directly. You would likely need to instigate this from within your template. I would suggest perhaps using a plugin variable either directly, or as a wrapper for your plugin service method (if you need to do something more complicated).

Something like the following:

Note: This is adapted from the 'BusinessLogicTemplate' plugin which provides a great starting point for plugin development.

<?php namespace Craft;

class MyPluginVariable
{

    /**
     * Whatever you want to output to a Twig tempate
     * can go into a Variable method.
     *
     * HOW TO USE IT
     * From any Twig template, call it like this:
     *
     *     {{ craft.myPlugin.exampleVariable }}
     *
     * Or, if your variable requires input from Twig:
     *
     *     {{ craft.myPlugin.exampleVariable(twigValue) }}
     *
     */
    public function exampleVariable($optional = null)
    {
        return "And away we go to the Twig template...";
    }
    public function formatBody($body)
    {
        /* process $body and return it to the template */
        return $body;
    }

}

Then in your template:

{{ craft.myPlugin.formatBody(entry.body) }}


Gitignore pattern to remove image transforms Not sure on the gitignore pattern I need to add to ignore craft's image transforms it automatically generates. Any ideas?

Those image transform folders all start with an underscore. The following pattern should work, if you don't set up underscore folders yourself:

public/assets/**/[_]*/


Is there a plugin like Compressor for Craft 3? Is there are similar plugin for Craft 3 like https://github.com/sathoro/Compressor?

I don't think there's a single plugin, but looking through https://plugins.craftcms.com it looks like maybe Minify and Asset Rev would do it together.


Error: URI already taken I've got a content type for team members but whenever I try to add one it gives me an error saying "the URI 'team' has already been taken".

I assume the URI is made from the slug, which is where I get the error.
The title of the team members is made automatically from the first name and last name.

And even when I type in the slug myself it keeps giving the same error. What's weird is that I was able to create one team member successfully but it started failing afterwards.

URI error:

Title settings:

(I'm writing this in case someone comes across the same problem)

As @MatsMikkelRummelhoff pointed out, I still had to change the URL's format settings to team/{slug}


Problem with getHeadHtml(), getFootHtml() and caching I have two problems when it comes to working with getHeadHtml() and getFootHtml().

But first things first. Here's my setup:

This is my stripped down _main.twig layout file:

<!DOCTYPE html>

    {{ getHeadHtml() }}
    <link rel="stylesheet" media="all" href="/assets/scss/styles.css" />

    {% block content %}{% endblock %}

    {{ getFootHtml() }}

This is my stripped down _entry.twig file:

{% extends "_layouts/_main" %}

{% block content %}
    {% for block in entry.cf_content_matrix %}
        {#
            Include all blocks
        #}
        {% include "_blocks/_block_" ~ block.type ignore missing %}
    {% endfor %}
{% endblock %}

This is the Matrix block that is causing the problems I have.
Basically it is a jQuery slider plugin. I only want the JS and CSS files injected when this block is actually used. So I thought that using includeCssFile, includeJsFile and includeJs would be a perfect fit for this.

{% set images = block.images %}

    {%- for image in images -%}

    {%- endfor -%}

{% includeCssFile "/assets/javascripts/slick/slick.css" %}
{% includeCssFile "/assets/javascripts/slick/slick-theme.css" %}
{% includeJsFile "/assets/javascripts/slick/slick.min.js" %}
{% set owlJs %}
    $(document).ready(function() {
      $("#screenshot-slider").slick();
    });
{% endset %}
{% includeJs owlJs %}

OK. So far so good. It works rather well.

Problem 1

The {{ getHeadHtml() }} in the _main.twig file is somehow ignored. Instead of injecting the CSS files BEFORE my styles.css files, they are injected just before the &lt;/head&gt; tag. As if it wasn't there.

Anybody experienced this behaviour?

Problem 2

This concerns caching.

When I try to cache the content matrix the following way:

{% extends "_layouts/_main" %}

{% block content %}
    {% cache %}
        {% for block in entry.cf_content_matrix %}
            {#
                Include all blocks
            #}
            {% include "_blocks/_block_" ~ block.type ignore missing %}
        {% endfor %}
    {% endcache %}
{% endblock %}

NOTHING get's injected. Neither the CSS files, nor the JS files.

Does anybody know why this is the case, and if there is a solution to it?

Any help appreciated!

Regarding Problem 1

The Twig function {{ getHeadHtml() }} does only work with JS/CSS that are included before this tag. I had the same problem... you can find the answer/explanation of Brandon Kelly here: getHeadHtml() not outputting CSS included with {% includeCss %}

Regarding Problem 2

The {% cache %} does only cache the output HTML, no variables (see Is it possible to cache variables using the {% cache %} tag?). As a workaround you could cache the {{ getFootHtml() }} as well: in the first request it process the complete Twig code and stores the getFootHtml content correct. With this solution, you need to delete the cache manually (or with the onAfterSave event) after (re)saving, and adding/deleting an entry that could affect the cache.
Note: This does not work with {{ getHeadHtml() }} (see Problem 1).


How do I pull out a total of 4 rows from all my matrix blocks? I have an entry that has a matrix field, which has a table in it; I am trying to pull out 4 rows from the latest block, but if there aren't 4 rows then I would like it to pull out the remainder from the older blocks (So I always have 4 items displayed, even if the latest matrix block only has 1 table row in it).

This is what I have so far, but this is pulling out the latest 4 rows from EACH matrix block, so if I have 2 blocks it displays 8 items.

Does anyone know if what I'm trying to do is possible?

{% for entry in craft.entries.section('sectionName').find() %}
    {% for block in entry.matrixField %}

    {% if block.type == "blockType" %}

        {% for row in block.tableField | slice(0, 4) %} <!-- I tried .limit(4) here too -->
            {{ row.title }}
        {% endfor %}

    {% endif %}

    {% endfor %}
{% endfor %}

Any help is appreciated!

I am assuming you want four rows from each entry. I would do it like this using {% break %} from the break and continue plugin:

{% for entry in craft.entries.section('sectionName').find() %}
  {# restart our count for the new entry #}
  {% set numberOfRows = 0 %}

  {% for block in entry.matrixField %}
    {% if block.type == "blockType" %}
      {% for row in block.tableField.limit(4) %}

        {# bail if we've done our 4 rows #}
        {% if 4 <= numberOfRows %} {% break %} {% endif %}

        {{ row.title }}
        {# done another row, count it #}
        {% set numberOfRows = numberOfRows + 1 %}

      {% endfor %}
    {% endif %}

    {# bail if we've done our 4 rows #}
    {% if 4 <= numberOfRows %} {% break %} {% endif %}

  {% endfor %}
{% endfor %}

Or, slightly less efficiently (but maybe simpler), like this without that plugin:

{% for entry in craft.entries.section('sectionName').find() %}
  {% set numberOfRows = 0 %}
  {% for block in entry.matrixField %}

    {% if block.type == "blockType" %}
      {% for row in block.tableField.limit(4) %}

        {% if numberOfRows < 4 %}
          {{ row.title }}
          {% set numberOfRows = numberOfRows + 1 %}
        {% endif %}

      {% endfor %}
    {% endif %}

  {% endfor %}
{% endfor %}

I don't think you pull out the four rows from multiple matrix blocks with a single query.


How can an entry type have its own search and categories? I have an entry type whose content will be separated from the main content. So I was wondering how can we give an entry type its own search and categories? Possible?

Sure it's possible. There's the type() parameter available for ElementCriteriaModels to filter the returned results by only those entry types you need.

To separate the categories, I'd set up multiple category groups, one for each of your entry types.

For example:

{% set categoryParams = {
    group: 'audioCategories',
    slug: 'podcasts'
} %}

{% set category = craft.categories(categoryParams).first() %}
{% set searchTerm = 'basketball OR soccer' %}

{% set entryParams = {
    section: 'news',
    type: 'audio',
    relatedTo: category,
    search: searchTerm
} %}

{% for entry in craft.entries(entryParams) %}
    <li>{{ entry.title }}</li>
{% endfor %}

This would list only those entries which are

in a section named "news"
given an entry type (and entry template) "audio"
related to a category from the category group "audioCategories" (I additionally filter for just the one cat. named "podcasts" to keep the example a little simpler)
matching to the search term "basketball OR soccer"


Customization Facebook OpenGraph Title I am using SEOmatic on Craft 2 and want to give the user the ability to customize the Title field of Facebook's OpenGraph Title. For example, instead of showing just the Title, add a "How To" before the title is displayed.

vs.

Is there a way to do this without using a custom field and have the "How To" only display only on when the article is shared on Facebook?

Referring to this page, you can try this:

{% set og = seomaticMeta.og %}
{% set og = og | merge({'title': 'How to: ' ~ seomaticMeta.og.title}) %}
{% set seomaticMeta = seomaticMeta | merge({'og': og}) %}


Load a page via HTTP and make an AJAX request via HTTPS afterwards using CSRF-Token I have the following scenario:

A page is loaded via HTTP
The user fills out a form and submits its contents via HTTPS
The craft CSRF prevention is enabled, so the previousy generated CSRF-Token is submitted along with the form
Craft responds with a HTTP 400, because the Token is not valid for the request being send over HTTPS

Is there a way to use Crafts CSRF prevention feature in this scenaria? So say for example tell Craft to generate the token for an expected HTTPS request?

Regards,
Clemens

Completely untested, but try setting the recently added useSecureCookies setting to false and see if that works.


Any ideas on how to set/output something if the previous variant in a for loop has a parameter? Realizing Twig can't escape a for loop, how would one go about setting a variable for the current item and not the following?

Scenario;
Color swatches are radio buttons, if default purchasable stock <= 0 and default purchasable unlimitedStock == false, the next radio button should be checked, and if this has stock <= 0 and so on, you get the idea, the next would be checked.

I can't seem to find a way to only check the next, and not all the following radio buttons if previous purchasable in the loop is out of stock.

A lot of checking of the checkers being checked here. Hah.

Check out the MN Twig Perversion plugin. It adds a break Twig tag, which allows you to escape from a loop once you have the data you need.


Find all empty fields in admin I'm working with a fairly large data set in one of my channels and I was hoping there was a way maybe in admin to show me all the live entries where certain fields are empty. I want to be able to easier find where I'm missing data. Any suggestions?

I can't think of a super-easy way to figure this out off of the top of my head.

There are a couple of not-so-easy ways to figure it out, though.

1) Find the column in the craft_content (or the equivalent Matrix content table) and find all the rows with empty values.

2) From either a plugin (PHP) or a template (Twig), write some code that grabs all of the entries you are interested in and loops through them checking if the particular field has a value or not.


Run Craft Find and Replace via Console I'm trying to streamline my deployments for local, staging and production and would like to know if it's possible to invoke the Find and Replace method via Console. I have a multi-config in place, but I'd like to ensure that any hardcoded urls are replaced in the database.

You can write a plugin that does this.

Use https://pluginfactory.io/ and check the "Console Command" checkbox and it will generate the boilerplate for you.

Your "Find and Replace" command would follow similar logic to what the FindAndReplaceTask's runStep() method does.


Correct way to set up development and production environments for Craft? I'm setting up a new site using Craft and would like to know what's the best way to manage dev and production environments? For instance, keeping entries/fields/ and control panels configurations sane across both environments?

I'd recommend you take a look at the excellent existing threads on this:

Git Workflow and Multi Environment - how to approach
What's the best practice for handling data migration and organization across development environments?

as well as the official documentation on Multi-Environment Configs


Show Matrix Assets from German language in other locales I have a website with three locales (de, fr, it). On a Matrix Field i have Assets where are only uploaded in German language. Now i'm trying to show those assets also in French and Italian language.

Any ideas to solve this? I have tried to put a .locale('de') to get the german fields, but if i change the language, the assets are not displayed.

Here is my code:

    {% for entry in craft.entries.section('sitemap','staticContent').status('live').slug(lastSegment).limit(1) %}

    {% for block in entry.multiContent %}

        {% if block.type == "documents" and block.downloadbarAlsDigitalesDokument == "1" %}

                    {% set items = block.datei %}

                        {% for item in items %}

                                 {{ item.title }}

                        {% endfor %}

        {% endif %}

    {% endfor %}

{% endfor %}

@carlcs helped me in Craft Slack. Many thx to him. The solution at the end was to pull out the asset field from the main matrix field and to put them in a separate without localisation enabled.


Retrieve entry data from an Entries field in a Matrix Block I'm using a Matrix field for menu section blocks that each have a name, section and menu items. The menu items for that menu section are assigned using an Entries fieldtype that displays entries from food and beverage entries. Here's a screenshot of the field setup in case that helps explain it better:

What I'm trying to do is generate a menu endpoint that has the individual sections and within each section display the item data. The json response I'm looking for should be similar to this structure:

        "menu": {
          "id": 1,
          "sections": [
            {
              "id": 1,
              "name": "Heavy",
              "description": "All our heavy draft beers.",
              "items": [
                {
                  "id": 2,
                  "name": "Samuel Adams Utopias",
                },
                {
                  "id": 3,
                  "name": "Samuel Adams Utopias",
                },
              ]
            },
            {
              "id": 2,
              "name": "Light",
              "description": "All our light draft beers.",
              "items": [
                {
                  "id": 2,
                  "name": "Samuel Adams Utopias",
                },
                {
                  "id": 3,
                  "name": "Samuel Adams Utopias",
                },
              ]
            },
          ]
        }

I can accomplish the section structure just fine, but I can't get the data from the sectionItems field which is an Entries type. This is what I have minus the items call.

        'api/v1/locations/<entryId:\d+>/menu.json' => function($entryId) {
          return [
            'elementType' => 'Entry',
            'criteria' => [
              'id' => $entryId,
              'type' => 'location'
            ],
            'first' => true,
            'transformer' => function(EntryModel $entry) {
              foreach ($entry->menu as $block) {
                $menuBlocks[] = [
                  'id' => $block->id,
                  'menu_id' => $block->fieldId,
                  'name' => $block->sectionName,
                  'description' => $block->sectionDescription,
                  'items' => $block->sectionItems,
                ];
              }

              return [
                'title' => $entry->title,
                'menu' => [
                  'sections' => $menuBlocks
                ]
              ];
            },
          ];
        },

Any help would be greatly appreciated!

You’re off to a great start here, in the way that you are first assembling the $menuBlocks array, and then finally returning the main array with the title and menu keys. For the section items, you just need to take the exact same approach:

'transformer' => function(EntryModel $entry) {
  // Note: you should also make sure you define the $menuBlocks
  // array, to avoid a PHP error in case there are 0 blocks.
  $menuBlocks = [];

  foreach ($entry->menu as $block) {
    // Now start by defining an $items array:
    $items = [];

    // And loop through your sectionItems field just like
    // you are doing with the menu field.
    // (Note - you can’t name the individual item entries "$entry",
    // because that would override the other $entry variable.)
    foreach ($block->sectionItems as $itemEntry) {
      $items[] = [
        'title' => $itemEntry->title,
        // ...
      ];
    }

    $menuBlocks[] = [
      'id' => $block->id,
      'menu_id' => $block->fieldId,
      'name' => $block->sectionName,
      'description' => $block->sectionDescription,

      // Now insert that whole $items array here:
      'items' => $items,
    ];
  }

  return [
    'title' => $entry->title,
    'menu' => [
      'sections' => $menuBlocks
    ]
  ];
},


How to get values into twig template for fields of type Matrix in Craft CMS 2? CMS: Craft CMS 2
In my admin panel I have globals set called X (under "Globals" from the sidebar and defined in craft_globalsets in the db from Global->Settings->New global set).
A field for the field layout for the global set is defined by using as Content a Field type Y of Matrix type with several plain texts fields A,B,C,...
How do I check/show such fields' values (A, B, C, ...) in twig?
What I have tried: I see that in the other parts of the code the handle defined in craft_globalsets (or equivalently in Settings->Globals) is used to fetch the globals' field value
e.g. for Globals -> set 'K' (handle in craft_globalsets: kHandle) there are several plaintext inputs and such are accessed in twig as:

{{ kHandle.firstField}}

and in fact it works - but when I od the same with set X

{{xHandle.firstFiledInTheMatrix}}

it's null
I have also tried to do

{%  set matrixFields = craft.fields.getFieldByHandle('Y') %}
{{  matrixFields }}

but this returned only the field name.
Perhaps I should do something like {{ xHandle.firstFiledInTheMatrix.getMatrixContent | getFieldContent }} and a for loop on this? (currently guessing the function names here)

You should be able to get your content by using a for loop on your Matrix field:
{% for blocks in kHandle.yourMatrixfieldHandle.all() %}
    {{ block.fieldHandle }}
{% endfor %}

Alternatively, if you only have one block in there, you could use:
{{ kHandle.yourMatrixfieldHandle.first().fieldHandle }}


How can I get only those entries with non-empty assets field Since Craft 2.0 it is possible to pass :empty: and :notempty: to ElementCriteriaModel parameters when you’re looking for empty/non-empty values. If you are for example looking for all entries with a non-empty text field myTextField, you can do this:

{% set entries = craft.entries.section('mySection').myTextField(':notempty:') %}

However this syntax doesn't work for asset fields and I can't figure out how that syntax has to be.

An alternative would be to use the search function:

{% set entries = craft.entries.section('mySection').search('myAssetField:*') %}

But I generally try to avoid using the search parameter in queries whenever possible. It is probably not that much of a performance killer but by avoiding it I don't have to worry about my search index.

Craft 2.5 introduced a new feature for this.

  It’s now possible to find elements where a relational field does/doesn’t have any related elements, by passing ':notempty:' or ':empty:' onto the field’s ElementCriteriaModel parameter (e.g. craft.entries.myEntriesField(':notempty:')).

So in this case you can use:

{% set entries = craft.entries.myAssetField(':notempty:') %}


"Logging In" From a Console Plugin? I am writing a console plugin to import a load of gallery images from an old site into a new craft site. I need to create folders in the assets area, import the images, then create custom entries to represent the galleries.

I am hitting a hurdle at the first task, creating a folder. It fails with a general message like "Error creating folder". I assume it's because I am not "logged in" and therefore have no permission to create the assets folder.

So I tried to do a craft()->userSession->loginByUserId(1) but I got the complaint about no ip address or user agent string. I checked the code and saw that there is a config item to turn this check off, but the method loginByUserId() doesn't use it.

Is there a way to force a login from a console plugin so that I can do privileged operations?

Craft 2 doesn't really have the concept of sessions or logging in for it's console app.

If I had to guess that error is more about file system permissions, but you'd want to check your log files for a full stack trace to see where it's originating from.


What are the best-practices for useful logging messages? I'm currently adding messages to the log when an error occurs in my plugin.

Now I'm wondering what such a message should contain, to provide useful information to developers and end-users?

.

Currently my logged errors/warnings look like this:

  "functionName": A simple explaination of the error:
  "$related_var"

Actual example:

  "_getUserGroupUsers": No Users found in UserGroups with ID: "1, 2"

.

Is this something a developer/user checking the logs would find useful, or should more information be passed? If so, what else?

Also are you just logging errors/warnings or also valid operations (something like a StackTrace)?

If you're throwing Exceptions from your plugin, then those will automatically get logged in Craft's log files at craft/storage/runtime/logs with full stack trace information, so there is no need for extra logging there.

In you're using Craft::log or PluginHandlePlugin::log statements, and you set LogLevel::Error, or LogLevel::Warning, then those messages will get logged regardless if devMode is enabled or not.  LogLevel::Info and LogLevel::Profile will only get logged if devMode is enabled.

Logging the actual method name isn't really necessary because even with devMode disabled, you'll get a few steps in the stack leading up to the message so you can determine where it came from.  You will want to pass in any relevant variable names and values to the log message, though.


Front End Form with Dropdown in Matrix - Adding New I've got a Matrix field called Emergency Contacts (handle: emergencyContact) that I'm setting up so that users can add/update on the front end.  It has one block type - contact - with 4 fields:

Name (Plain Text - handle: contactName)
Relationship (Dropdown - handle: contactRelationship)
Phone (Input Mask - handle: contactPhone)
Email (Plain Text - handle: contactEmail)

I have everything displaying correct when I show existing information.  However, when they go to enter a new emergency contact, I can't figure out the right syntax to populate the dropdown menu to populate with the options for them to select.

Below is my code.  I've tried several different things, most of which gave me an error.  This is my latest attempt.

<input type="hidden" name="fields[emergencyContact][new1][type]" value="contact">
<input type="hidden" name="fields[emergencyContact][new1][enabled]" value="1">

    <fieldset class="cell small-3">
        Name<input type="text" name="fields[emergencyContact][new1][fields][contactName]">
    </fieldset>
    <fieldset class="cell small-3">
        Relationship
        <select name="fields[emergencyContact][new1][fields][contactRelationship]">
        {% for option in contactRelationship.options %}
            <option value="{{ option.value }}">{{ option.label }}</option>
        {% endfor %}
        </select>
    </fieldset>
    <fieldset class="cell small-3">
        Phone<input type="text" name="fields[emergencyContact][new1][fields][contactPhone]">
    </fieldset>
    <fieldset class="cell small-3">
        Email<input type="email" name="fields[emergencyContact][new1][fields][contactEmail]">
    </fieldset>

Anyone able to help me get this resolved?

Your Code has two errors:
1.  was missing.
2. The way you were fetching options was wrong.

Here is the correct code:

<input type="hidden" name="fields[emergencyContact]" value="">
<input type="hidden" name="fields[emergencyContact][new1][type]" value="contact">
<input type="hidden" name="fields[emergencyContact][new1][enabled]" value="1">

    <fieldset class="cell small-3">
        Name<input type="text" name="fields[emergencyContact][new1][fields][contactName]">
    </fieldset>
    <fieldset class="cell small-3">
        Relationship
        {% set matrixField = craft.fields.getFieldByHandle('emergencyContact') %}
        {% set blockTypes = matrixField.getFieldType.getSettings.getBlockTypes %}
            {% for blockType in blockTypes %}
                {% if blockType.handle == "contact" %}
                     {% for field in blockType.getFields() %}
                       {% if field.handle == "contactRelationship" %}
                          <select>
                          {% for option in field.settings.options %}
                             <option value="{{ option.value }}">{{ option.label }}</option>
                           {% endfor %}
                           </select>
                        {% endif %}
                      {% endfor %}
                 {% endif %}
              {% endfor %}
    </fieldset>
    <fieldset class="cell small-3">
        Phone<input type="text" name="fields[emergencyContact][new1][fields][contactPhone]">
    </fieldset>
    <fieldset class="cell small-3">
        Email<input type="email" name="fields[emergencyContact][new1][fields][contactEmail]">
    </fieldset>

I hope it helps you.


Craft plugin or external application My question is more conceptual than technical;

I have a website who have two big topics, on is purely editorial (pages, articles, faq, ...), the other is basically a comparator based on user input with account, sending contracts by mail and by post, reminders, signatures, etc etc. The business logic is quite complex.

I started doing everything in laravel + nova admin but I quickly felt frustrated for the cms part, as I'm used to Craft, and everything where Craft is good at is a pain and takes time to recreate in nova (the tool is an admin that has some cms capabilities, but is really far form Craft).
So I ended up with two applications, Craft for content editing, and Laravel + nova for the custom part.

Is it a good idea ? Or should I put custom parts in custom craft plugins ? Can I do eveything, I guess like yii apps ?

In my current situation, I fear that I will end up with more complexity, making the two applications communicate seamlessly will take time, maybe mix authentifications,...
In the other hand, I have the impression to really own the codebase and database with a barebone laravel app, than putting everything into Craft, as good as he is. But it's maybe a noob assumption.

What in your experience is the best way to go ?

Thanks for your inputs !

In my company we work with Craft and Laravel only, so this question comes up quite often and is a moving target as time passes and both platforms evolve.

Since Craft is built on Yii you can do almost everything what you can do with Laravel. You have basically 3 options here: Craft-only, Nova-only or a hybrid. I would ask myself at least the following questions to make a decision:

Do you need to write a lot of tests for the business logic? -> even though Craft caught up on testing, still +1 for Nova and Laravel
Is the editorial part of the application really trivial? Like, can you avoid having complexity in the editorial and business logic part of the application? -> +1 for the hybrid
Do both parts of the application really have to communicate with each other? Can you avoid a shared user authentication? (should generally considered as last option IMO) -> +1 for the hybrid
What about integrations, are there plugins/packages available that you can use right away? -> depends on the research
Is there any show stopper for the business logic part regarding Craft? (Arbitrary example: You need a multi-tenancy architecture, don't take Craft-only.)

So in the end the good news is, there is not necessarily a right or a wrong answer here. The bad news is, either way you go you'll always feel like: "What if I had..."

You see, personally I lean more towards Laravel for custom application development, just because I am more comfortable with it than with Yii. I would definitely consider to take the advantages of both platforms in exchange for a bigger code base and maintenance effort. But only if one application part can be dumb and the other complex.

Maybe now you are even more uncertain than before :)


How do you save custom fields on an EntryFixture? I can't for the life of me figure out how to setup EntryFixtures in craft to populate with custom fields. I'm using the project config which already has the sections and fields defined in my tests. I'm trying to set a field, gmbId, that's set on a locations entry type. Here's my code. I feel like I'm missing something basic here.
codeception.yml
actor: Tester
paths:
  tests: tests
  log: tests/_output
  data: tests/_data
  support: tests/_support
  envs: tests/_envs
bootstrap: _bootstrap.php
params:
  - tests/.env
modules:
  config:
    \craft\test\Craft:
      configFile: "tests/_craft/config/test.php"
      entryUrl: "http://host.docker.internal/index.php"
      projectConfig: {
        folder: "config/project",
        reset: true
      }
      migrations: []
      plugins: []
      cleanup: true
      transaction: true
      dbSetup: { clean: true, setupCraft: true }

LocationFixture.php
<?php

namespace tests\fixtures;

use craft\test\fixtures\elements\EntryFixture;

class LocationFixture extends EntryFixture
{
    public $dataFile = __DIR__ . '/data/locations.php';
}

locations.php
<?php

return [
    [
        'sectionId' => $this->sectionIds['locations'],
        'typeId' => $this->typeIds['locations']['locations'],
        'title' => 'Location 1',
        'gmbId' => '123' # this is the custom field I'm trying to set.
    ],
    [
        'sectionId' => $this->sectionIds['locations'],
        'typeId' => $this->typeIds['locations']['locations'],
        'title' => 'Location 2',
        'gmbId' => '123'
    ],
    [
        'sectionId' => $this->sectionIds['locations'],
        'typeId' => $this->typeIds['locations']['locations'],
        'title' => 'Location 3',
        'gmbId' => '123'
    ]
];

Prepending the field name with field: should do the trick.
<?php

return [
    [
        'sectionId' => $this->sectionIds['locations'],
        'typeId' => $this->typeIds['locations']['locations'],
        'title' => 'Location 1',
        'field:gmbId' => '123',
    ],
];

See https://github.com/craftcms/cms/blob/develop/tests/fixtures/data/entry-with-fields.php for reference.


Craft 3 CMS Solo setting general Logo option I have installed Craft 3 Solo and it's installed on my local machine. I would like to know how can I get an option in Setting -> General to Logo (upload Login Page Logo).

I am new to Craft, so would like to get a little bit of guidance.

Thanks.

The login logo option is only visible with Craft Pro’s rebranding options. So, if you need this, you’d need to upgrade to Pro (or give it a  try without purchasing it, if you’re on a dev-domain).


Sending attachments within a plugin Using Craft 2. Here's my code, which sends the email fine if I remove the attachment part. Can anyone point me in the right direction?

$email = new EmailModel();
$email->toEmail = $toEmail;
$email->cc = $ccEmail;
$email->bcc = $bccEmail;
$email->subject = $subject;
$email->body = $body;
//$email->attachments = $attachments;

$attachments = [
  ['path'=>'http://website.localhost/img/uploads/nameoffile.pdf',
  'name'=>'afile',
  'encoding'=>'base64',
  'type'=>'application/pdf']
];
if (!empty($attachments)) {
  foreach ($attachments as $attachment) {
    if ($attachment) {
      $email->addAttachment($attachment['path'], $attachment['name'], 'base64', $attachment['type']);
    }
  }
}

if ($email->getErrors()) {
  throw new Exception('there are errors'); // exception not returned
}

// SEND THE MAIL
if (craft()->email->sendEmail($email)) return true;
else throw new Exception('not sent'); // returns this exception

Craft 2 uses the PHPMailer library to send emails and the first thing its addAttachment() method does is take the first $path parameter that's passed in and run PHP's is_file() on it.

is_file() won't work on URLs like you're passing in, it expects the file to be on the local file system, so you'll need to download it locally and pass in that path.

It won't show up on the model as an error using $email->getErrors() because the library catches the exception, does some internal logging and returns false.  Craft doesn't have a change to add that particular error back on its EmailModel.


Channel index page linked in a structure I come from expression engine and what I want to do is the following: I have a channel filled with entries. All I want to do is to list all these entries on a page.
However, I don't want to link through to a detail page. So I disable the "Entries have their own URL's".

Now I can link to this channel by linking to its handle in my url.

Problem now is that I use a structure to build up my navigation. And you can't link to a channel in a structure, only to its entries. So I need to create a (useless) extra single section to link to and list all entries from my channel in that single.
Shouldn't it be simpler than that?

I didn't find a better way to handle navigations yet.

The reason why there's no automatically set url and template for channel index pages is because Craft tries to be as flexible as possible. In many use cases for channel sections you don't want a index page at all or you could also need multiple of them.

But you already chose a very solid approach by setting up a structure section for your navigation. And no, you don't have to create useless singles for each channel index. I'd rather use entries of that structure itself and would just set up a new entry type for your indexes. See this article in the Craft Docs on how to link templates to entry types.

I think it's really nice to have all the site main pages together in one structure. You can easily add fields to your index pages and have your client edit all this rather static content in here.

You can also add you home page to that structure. See this Q/A for how to do that.


Importing Macros doesn't work I'm trying to upgrade my website to Craft 3, so I've imported all template files and installed the necessary plugins, but I can't deal with one error.

I've got a template named _layout.twig, and the first line used to import macros from other file called _helpers.twig. For some reason this doesn't work on Craft 3 - I checked in Twig documentation and it seems that everything is correct. I reviewed the changes in Craft 3 but didn't find anything related there. Running Craft 3.3 with Twig 2.11.3.

_layout.twig

{% import '_common/_helpers' as helpers %}
{{ helpers }}

Error

  Twig Runtime Error – Twig\Error\RuntimeError
  Variable "helpers" does not exist.

  in /craft3/templates/_layout.twig at line 2

Any ideas what can be the issue here?

I think you need to reference a macro name inside of your _common/_helpers file.

For example:

{{ helpers.input('username') }}

That would output a macro called input:

{% macro input(name, value, type = "text", size = 20) %}
    <input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}" />
{% endmacro %}


Failed Task and various errors in logs I've got a few issues with a site but I'll try to separate in case they're not related.

Firstly I keep getting "Failed task - Deleting stale template caches".

I've looked in the logs and some messages include:

  Encountered an error running task 3 (DeleteStaleTemplateCaches), step 156 of 166: An exception was thrown: CDbCommand failed to execute the SQL statement: SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'dateCreated' in order clause is ambiguous

and

  CDbCommand::fetchAll() failed: SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'dateCreated' in order clause is ambiguous. The SQL statement executed was: SELECT elements.id, entries.sectionId, entries.typeId, entries.authorId, entries.postDate, entries.expiryDate

Similar to How to fix "ambiguous" column error generated when DeleteStaleTemplateCaches is run?

But somewhere, in one of your templates that are using the {% cache %} tag, you're ordering by dateCreated in your template and it should be elements.dateCreated.

The {% cache %} tag has already picked up the invalid Twig code and cached it to the database so whenever the DeleteStaleTemplateCaches task tries to run, it trips up on the invalid Twig.

So after you fix the original error, you'll want to clear your template caches using the Clear Caches tool under settings in the control panel to purge the invalid cached code as well.


Random duplicate DB query issue Can anyone shed any light on this duplicated db query issue?
I've noticed when going through my site with the debug toolbar on, sometimes when I click a page or entry there is often double the amount of DB queries being run than normal? And when I look at the details it's often just every query duplicated?
If I refresh the page the proper amount of queries are run and TTFB is exactly half. It's worth noting regardless of whether 'disable cache' is set in Chrome Dev tools this happens. If I navigate to another area of the site and come back, it's hit and miss whether the duplicated queries are run. On manually refreshing the same page the correct number of queries always run...
What do you think would be causing this? I've eager loaded everything thing that I can on each template and performance is generally very good but random duplicate query issue is baffling me.
Edit: Seems to be only happening on my main entry template.
I've removed all the code from this template to only leave in basic scripts and it still spits out 100 db queries and says 50% of them are duplicate. But in the template there are no queries to even be made??

Looks like SEOmatic is the culprit and not Blitz caching plugin as first thought.


Unable to set planAmount for Charge 2 - Stripe I keep getting an error response for my test field for Charge. I've pretty closely followed the example just for testing and can't seem to get a successful charge.

I've tried setting a hidden field for amount and planAmount to no success.

Error:

array(1) {
  ["errors"]=>
  array(2) {
    [0]=>
    string(37) "planAmount : Amount must be a number."
    [1]=>
    string(74) "There was a problem with your details, please check the form and try again"
  }
}

Form:

<form method="post" id="charge-form" class="charge-form">
    <input type="hidden" name="action" value="charge/charge">
    {% set options = {
        'planAmount': 79,
        'planInterval': 'year',
        'planIntervalCount': 1,
        'planCurrency': 'aus',
        'actions': {
            'onSuccess': {
                'subscription': 'gold-membership'
            }
        }
    } %}
    {{ craft.charge.setPaymentOptions(options) }}

        Receipt Email
        <input type="text" name="customerEmail" value="{{ charge is defined ? charge.customerEmail : currentUser ? currentUser.email }}" id="customerEmail">
        {% if charge is defined %}{% for error in charge.getErrors('customerEmail') %}{{ error }}{% endfor %}{% endif %}

        Card Number
        <input type="text" data-stripe="number" placeholder="•••• •••• •••• ••••" id="cardNumber">

            Expiration (MM/YY)
            <input type="text" size="2" data-stripe="exp_month">

         /
        <input type="text" size="2" data-stripe="exp_year">

        Card CVC
        <input type="text" data-stripe="cvc" placeholder="123" id="cardCvc">

    <button type="submit">Upgrade</button>
</form>

JS:

Stripe.setPublishableKey(this.s.publicKey.test);
$(window).charge(this.s.form);

Developer of Charge here.

This error is because you're passing an invalid currency code.

You're passing aus as the planCurrency, but need to be passing aud for Australian Dollars.

Under the hood, Charge is seeing that currency code as invalid, and unsetting the amount from the request, which is why that error is showing up on the planAmount.

(Charge unsets the amount as a safety mechanism to prevent the request falling back and processing in the default currency)

I'll update the language of the error to make it clearer the currency code is the invalid value in an upcoming release.


How to loop through matrix block fields and pull out handle and content? Ok this is similar to a previously asked question How to display all fields belonging to current entry?

However I'd like to extend this so that it deals with matrix entry types. I have the following but I just need to know how to loop through all the blocks and pull out each blocks entry field handle and content. Any help appreciated.

{# loop through the fields in the entries fieldLayout Model #}
{% for fieldLayoutField in entry.getFieldLayout().getFields() %}

    {# get the field Model from the fieldId #}
    {% set field = craft.fields.getFieldById(fieldLayoutField.fieldId) %}

    {% if field.type == 'Matrix' %}
        {% set matrixHandle = field.handle %}
        {% for field in matrixHandle %}
            ...loop through matrix blocks fields and pull out field handles and content...
        {% endfor %}
    {% else %}
        {# print the field handle and the field content  #}
        {{ field.handle }} : {{ entry.getContent()[field.handle] }}
    {% endif %}

{% endfor %}

I find accessing content like this pretty unintuitive, but I think you will need to use the Twig attribute method.  Hopefully the below can help keep you moving in the right direction.  I've simplified to just accessing the Matrix Field and I've made an assumption that you know the Matrix field handles you will want to access.

{% for fieldLayoutField in entry.getFieldLayout().getFields() %}
  {% set field = craft.fields.getFieldById(fieldLayoutField.fieldId) %}

  {% if field.type == 'Matrix' %}

    {# Dynamically access the Matrix Field on the Entry Model #}
    {% set matrixField = attribute(entry, field.handle) %}
    {% for block in matrixField %}

      {# Output your Matrix Field Handle #}
      {{ field.handle }}

      {# Output your specific fields content #}
      {{ block.fieldHandle }}

    {% endfor %}

  {% endif %}
{% endfor %}

You may also want to take a look at how Craft handles outputting Forms in the CP in the app/templates/_includes folder, starting with forms.html and reviewing the many related files.   Doing a task like this cleanly really requires a pretty deep level of abstraction if you don't want to make any assumptions about your variable names.


Fuzzy search in Asset Library Has anyone out there found a way to do a fuzzy search in the Asset Library? Currently, search only seems to return results that match the exact search query. Any help or plugin link is greatly apprecitated!

You can do a fuzzy search using the * character.  See here for a list of supported syntaxes.

Update:
As of Craft 2.5, you can enable fuzzy searching by default.


Translatable dropdown menu Does anyone know how to make the dropdown field translatable?

I'm working on a site which has both English and German languages, but whenever I set up a dropdown field it only ever appears in English and I don't have an option for the German version.

EDIT: I'm needing this to work as a dropdown on the German site also and not through templating {{ "word" | t }} as I need the client to have total control of this feature.

Any help would be appreciated — thanks.

It does it per default:

public function getInputHtml($value, ElementInterface $element = null): string
{
    return Craft::$app->getView()->renderTemplate('_includes/forms/select', [
        'name' => $this->handle,
        'value' => $value,
        'options' => $this->translatedOptions(), //<-- here are your translated options
    ]);
}

But you need to insert your translations into your translation files for the site category

protected function translatedOptions(): array
{
    $translatedOptions = [];

    if ($this->options) {
        foreach ($this->options as $option) {
            $translatedOptions[] = [
                'label' => Craft::t('site', $option['label']),
                'value' => $option['value']
            ];
        }
    }

    return $translatedOptions;
}


|replace filter is matching too many characters I'm looking to format out image tags from a string using the |replace filter. The behavior I'm looking for is to give it a string like this:

some text

and get back:

some text

Unfortunately, when I use {{ snippet|replace('//', '') }} it matches the entire string, from the opening  rather than matching both  tags individually. How can I force the regex to match only through the first > it finds before continuing?

Something like this should work:

{{ snippet|replace('/<img([\w\W]+?)>/', '') }}

You can see an explanation of the regex in the right column of https://regex101.com/r/DvJHeY/1


Custom plugin settings add on admin nav bar I want to control my plugin on the admin navbar but I can't found a way for that.

You need to use the EVENT_REGISTER_CP_NAV_ITEMS event in the main plugin class. From the docs:
use craft\events\RegisterCpNavItemsEvent;
use craft\web\twig\variables\Cp;
use yii\base\Event;

public function init()
{
    parent::init();

    Event::on(
        Cp::class,
        Cp::EVENT_REGISTER_CP_NAV_ITEMS,
        function(RegisterCpNavItemsEvent $event) {
            $event->navItems[] = [
                'url' => 'section-url',
                'label' => 'Section Label',
                'icon' => '@mynamespace/path/to/icon.svg',
            ];
        }
    );

    // ...
}


Localize custom element types I explored the events plugin (from https://github.com/pixelandtonic/Events) and I understand the most of that. Now I will try to make the events localized.

The Event itself has no localized field, just the fieldLayout fields. Do I have to save a second record in the event db or did I just have to save the element with the corresponding locale id?

Can you give me a hint what steps are needed that I can edit them in two languages?

So far, I load an existing event

craft()->elements->getElementById($eventId, 'Events_Event', $locale);

with the new locale parameter and create the edit form, putting the locale as hidden field to the form ('de' instead 'en'). The fieldLayout fields are showing the 'de'-icon above the input fields.

When I try to save it, I pass through the locale in the $event variable to
craft()->elements->saveElement($event)

I do not pass it to the $eventRecord because the $eventRecord itself didn't have a locale.

The event will be saved, just not in 'de' but in 'en'.

Do I have to tell the elementtype or the model that it can be localized to make it work?

I got it. I added this function to the Event_ElementType

public function isLocalized()
{
    return true;
}

This adds a language selector to your event index.

Then I enhanced the locale to the URL in getCpEditUrl() of the EventModel:

$locale = (craft()->isLocalized() && $this->locale != craft()->language) ? '/' . $this->locale : '';
return UrlHelper::getCpUrl('events/'.$calendar->handle.'/'.$this->id . $locale );

The additional route for the locale edit form is like this:

events/(?P<calendarHandle>{handle})/(?P<eventId>\d+)/(?P<locale>[-\w\.*]+)' => array('action' => 'events/editEvent')


Simple save data to db in Craft CMS I am new to Craft CMS.  Please tell me about how can I save data into database in Craft?

I have searched a lot of results about my query but nothing give advantage to me.

Thanks in advance.

I suggest you to read about the Yii Query Builder

craft()->db->createCommand()
    ->insert('mytablename', array(
        'field1'    => 'foo',
        'field2'    => 'bar'
    ));

Or you can use Active Records in Craft

$record = new Record();
$record->field1 = 'foo';
$record->field2 = 'bar';
$record->save();

Or you can use Craft Elements (entries/categories/tags)

$entry = new EntryModel();
$attributes = [
   'section'   => $yourSectionId,
   'entryType' => $yourEntryTypeId,
   'field1'    => 'foo',
   'field2'    => 'bar'
];
$entry->getContent()->setAttributes($attributes);
craft()->entries()->saveEntry($entry);


Can globals be localized? In the multi-lingual site I'm building, I've created an "SEO" global set where my client can enter keywords and a description to populate meta tags site-wide.

Problem: globals don't seem to be translatable.

So unless I'm missing something, I'll have to add additional dedicated fields to hold the Spanish version of this info.

Am I missing something? How would you approach this, if you'd do it differently?

Thanks!

Yes, globals can be localised. Make sure you have ticked "This field is translatable" in the field settings for the ones in your global set, and you should be good to go.


Controller action works but still gives 404 I'm writing my first plugin and I'm slowly getting there, but I hit on a problem:

I have a controller class in which I have a function that sets a cookie.
I call on this function from within a template with actionUrl().

The weird thing is, the cookie is being set (so the controller action is found and executed) but I still get a 404 page on the action path.

Anybody has an idea what could be wrong?

You're definitely on the right track, just missing out on a couple of key details!

The actionUrl function generates a normal, full URL... it's not (by default) an AJAX call. So your browser is actually navigating away from the previous page, and pinging your controller as a completely separate HTTP request.

Which leads to the next detail... Unless you're pinging your controller via AJAX, you need to then have your controller tell the request where to go. Don't forget, the request will continue on, even after your controller has worked its magic.

  ... if the controller doesn’t call a response function, Craft will continue on with its request routing...

So you'll usually want to make sure your controller ends with a directive on what to do next. The most common options are:

Render a template
Redirect to a new page
Return a JSON response (if you called it via AJAX)

The list of options to render/redirect/return are mixed in with the other BaseController Methods in the documentation...


Migration from “Focal Point Field" for Craft to Native Craft 3 image focal point Is there a migration from the “Focal Point Field for Craft“ plugin to the Craft3 native focal point? Or has anyone tried this themselves?

The inherent problem that you're going to have is that Craft CMS 3 focal points are per asset, and Focal Point Field is per field.

So you could have multiple Focal Point Fields that have different Focal Points for the same Asset... and then how would you map them?

A migration could be done, but there would have to be some compromise to take the above into account.


Why can't users upload files in this asset? I've two user groups; admin and user. The User group does not have access to the Assets tab, which stops them from just browsing all the assets that anyone might have uploaded - which is what I want; no random looking about in the Assets resources.

I've a field type 'Featured Image' that is an asset; and it is restricted to a single upload folder, file type image, with an upload location set to {slug} - this means it will upload files into a folder named the same as the slug for the entry in which it's being used.

It works fine for admins who have privileges to see Assets. I can not upload anything in this field with a user of type User.

This behaviour makes Asset fields essentially useless unless the user group also has privileges to view (and upload/edit) all assets site-wide. Because 'upload' is a child privilege of 'view assets' I can't give the upload rights without also giving them 'browse all the assets everywhere' rights.

I'd like these restricted users to be able to upload in that field.

Oddly, I have a Matrix field called Gallery which has an asset field inside it, set to file type image, single upload directory; {owner.slug}/gallery/

That asset field works fine for these users, and they are able to upload into it.

Anyone have any ideas?

I'd hoped this would be fixed in 2.3, alas it seems not, unless there's something I need to change?

Here's my experience as a mini screencast, logged in as a restricted user type (no assets privileges): http://viewcreative.co.uk/DELETEME/uploading.gif And here's the filetype set up and permissions: http://viewcreative.co.uk/DELETEME/permissions.gif

Have you checked the user group permission settings page? There you should be able to select which Asset Sources users in a specific user group are able to view, upload files to, etc. If at least one Asset Source is selected then the Assets navigation item will appear for users in that group, otherwise it will be hidden.


Passing variables between sibling blocks Is there any possibility to use "entry" from the for-loop inside the "main" block inside another block ("header" in my case)? See example below:

{% extends "main" %}
    {% block header %}
        {{ entry.id }}
    {% endblock %}

{% block main %}
    {% for entry in craft.entries.section('blogPosts').limit(5).all() %}
    {% endfor %}
{% endblock %}

I don't understand what you want to achieve? In your example, the for loop would run 5 times so which entry.id do you want to get out?

The way to use common variables in both your blocks would be to do:

{% extends "main" %}
{% set entries = craft.entries.section('blogPosts').limit(5).all() %}

{% block header %}
    {% for entry in entries %}
        {# access entries in here #}
    {% endfor %}
{% endblock %}

{% block main %}
    {% for entry in entries %}
        {# and also in here #}
    {% endfor %}
{% endblock %}


Locales - New locales not copying assets across I have a site made in English and need to add another locale that will be almost identical to the original site. However while adding new locales everything bar the asset entries are being copied. This is a problem as there are already many articles with image asset fields and new articles are not copying assets across locales either.

I have tried making the asset field Translatable and Not Translatable. These fields are not in a matrix.

UPDATE: Solved - What was needed was to use the Update Asset Indexes tool in the settings of craft. If I do this just after creating a new Locale, before doing anything else, when my articles are created they know where to look for their assets. So relieved

Solved - What was needed was to use the Update Asset Indexes tool in the settings of craft. If I do this just after creating a new Locale, before doing anything else, when my articles are created they know where to look for their assets. So relieved

Also noticed that to get a matrix to copy across locales (as well as setting the matrix field to NOT TRANSLATABLE and the fields within the matrix to TRANSLATABLE) it was necessary to do a slight change to the original matrix after creating a new asset (such as adding a space after the title). This forced the matrix to copy across.

Hope this helps someone else


How to show flash message for Commerce order when changing status on listing page? If I change an order's status to "Cancelled" (my custom order status I created), I want to ensure that the CP editors provide a "Cancellation Reason" from a dropdown field in the order.  I've set up a custom validator to do this but it doesn't get recognized in Commerce's flash message.

In my plugin, I'm adding a custom rule to Order elements like:

use my\plugin\validators\CancellationReasonValidator;
use craft\events\DefineRulesEvent;
use craft\commerce\elements\Order;
use yii\base\Event;

Event::on(
    Order::class,
    Order::EVENT_DEFINE_RULES,
    static function(DefineRulesEvent $event) {
        /* @var Order $order */
        $event->rules[] = [['cancellationReason'], CancellationReasonValidator::class];
    });

My validator looks like:

use Craft;
use craft\commerce\elements\Order;
use yii\validators\Validator;

class CancellationReasonValidator extends Validator
{
    public function validateAttribute($model, $attribute)
    {
        $cancellationReasonField = $model->$attribute;

        /* @var Order $model */
        if (   $model->isCompleted
            && $model->getOrderStatus()->handle === 'cancelled'
            && ! $cancellationReasonField->value) {

            $this->addError($model, $attribute, Craft::t(
                'site',
                'A cancellation reason is required for {orderNumber}',
                ['orderNumber' => $model->shortNumber]
            ));

        }
    }
}

If I edit an order, change the status to "Cancelled", and click the red update button, the validation works:

However, if I do this from the orders listing view, where I try to update an order's status like in the screenshot below, there is no flash message displayed to the user that the order couldn't save.

I understand there's a lot of asynchronous JS happening here, but how do I tap into showing some sort of message to my CP editors, preferably one that mentions the order's shortNumber?

I haven't tried this yet, but I think you can try to use "Server Side Event" with "Control Panel JS plugin for Craft CMS": https://github.com/doublesecretagency/craft-cpjs/blob/v2/README.md

Listen to server and append a custom alert when some event triggered at server side.

Here is some information about SSE.

W3S:
https://www.w3schools.com/html/html5_serversentevents.asp

SSE Browser Support:
https://caniuse.com/#search=Server%20Side%20Event

SSE Polyfill to Support Mobile Android and IE8+
https://github.com/Yaffle/EventSource

Yii2 SSE Server Side Example:
https://www.yiiframework.com/wiki/329/real-time-display-of-server-push-data-using-server-sent-events-sse

Yii2 SSE component:
https://github.com/odannyc/yii2-sse

Hope this helps.


Craft 3 How to get custom user field values I have following custom fields for users.

favouriteEntries - 'entry' type field with multiple entries per user
notificationPreference - Lightswitch field

My plugin should email notifications to users who follow that entry when there is an update to a particular entry (Entry::EVENT_AFTER_SAVE).

use craft\elements\User;

$users = User::find()->all();

With the above code, I can get all user data including notificationPreference but favouriteEntries. favouriteEntries field returns null even if it has entries for all users.

What's the correct way to get all user data including favouriteEntries field?

You should be able to access the custom fields on element\user object.

Craft::$app->getUser()->getIdentity()->getFieldValue('customfieldname');


Getting Template Errors When Using Cache Tag in some environments but not in others I'm having an issue where I am getting template errors related to my craft cache tags in some environments but not others. I have my site set up on a production server that is a Linode/Forge setup. The site works fine there.

Locally I am using a Homestead/Vagrant setup and I am getting template errors on any pages that use the cache tag.

Here's the code that is having the error:

{% extends "_layout" %}

{% block pageStyles %}

{% for entry in craft.entries.section('juices') %}
    .color-nameplate.btn-{{entry.slug}} {
        background-color: {{entry.productColorCode}};
    }
{% endfor %}

{% endblock %}

{% block bodyClass %}home-page{% endblock %}

{% block content %}

{% cache if craft.config.cache %}

{% for row in entry.bodyBuilder.level(1) %}
    {% include 'bodyblocks/' ~ row.type.handle with {row: row} %}
{% endfor %}

{% endcache %}

{% endblock %}

This code works in the production environment but not on local. On local it is showing the following template error:

  Unexpected token "name" of value "craft" ("end of statement block" expected).

If I remove the cache tags then the template displays, but this won't work for my production environment so I need to work out what the issue is.

Thanks,

Brian

So you're accessing craft.config.cache but unless you've actually added your own cache config setting in craft/config/general.php that's not going to work. There's no cache setting in Craft's Config Settings

So the reason it works on live production is it's a soft error, and you have devMode off, so it continues to work. In local dev, presumably you have devMode on, so it rightly errors.

For more information on Craft cache tags, you can read the The Craft {% cache %} Tag In-Depth article.


Problem with \craft\elements\User::EVENT_AFTER_SAVE Having an issue with using the event \craft\elements\User::EVENT_AFTER_SAVE in a plug in. I am adding a new user to a group. My goal is to have the newly added user automatically added to the same user group as the logged in user. This is my code:

Event::on(
    \craft\elements\User::class,
    \craft\elements\User::EVENT_AFTER_SAVE,
    function(ModelEvent  $event) {
        if (Craft::$app->getUser()->getIsAdmin() == false){
            $loggedInUser = Craft::$app->getUser();
            $userGroupUser = new UserGroup_User();
            $userGroupUser->groupId = $loggedInUser->getIdentity()->getGroups()[0]['id'];
            $userGroupUser->userId = $event->sender->id;
            $result = $userGroupUser->insert();
         }
    }
);

I have put a breakpoint on the code after the if statement and then checked the users table - the new user is not in the users table yet.

I would expect that the new user would be in the table at this point. Is this transaction being saved and executed later? If so is there something I can do to force the transaction to save the new user?

Is this possible a bug?

I do not get any error messages. Why?

EDIT: I should also mention that the usergroup has permission to add users in their own usergroup.

I don't know what your specific error is, but whenever I use

Event::on(
\craft\elements\User::class,
\craft\elements\User::EVENT_AFTER_SAVE,

I need to provide the next parameter with a \yii\base\Event callback, not a \craft\events\ModelEvent one.

Maybe that's your case as well ?
 You can also use \yii\base\ModelEvent, but not the craft one, as the craft ModelEvent does not extend \yii\base\Event


How get field type in field layout I'am building a website (craftcms 3.4+) where I'll need frontend entry editing. Therefore I'll need the fieldlayout of an entry. This is what I'll have:

{% for tab in entry.fieldLayout.tabs %}

{{ tab.name }}

        {% for field in tab.getFields() %}

                {% if field.type == 'plainText' %}
                    {{ field.name }}
                    <input type="text" name="fields[{{ field.handle }}]" value="{{ attribute(entry, field.handle)}}">
                {% endif %}

        {% endfor %}
{% endfor %}

The problem of this is that field.type not excist. I'll need that because of the different field types I'm using. How I'll get the th

You can use the instance of test (docs)

{% if field is instance of ('craft\\fields\\PlainText') %}

or use className (docs).

{% if field.className == 'craft\\fields\\PlainText' %}

In full:

{% for tab in entry.fieldLayout.tabs %}

{{ tab.name }}

    {% for field in tab.getFields() %}

            {% if field is instance of ('craft\\fields\\PlainText') %}
                {{ field.name }}
                <input type="text" name="fields[{{ field.handle }}]" value="{{ attribute(entry, field.handle)}}">
            {% endif %}

    {% endfor %}
{% endfor %}

You can see all native Craft field types here.


How can i output my content in pairs? how can i output my content in pairs?

like this:

div.row >   entry 1 + entry 2
div.row >   entry 3 + entry 4
div.row >   entry 5 + entry 6

so far i have the following

{% for entry in craft.entries.find({section:'events' ,level: 2 }) %}
<div class="row">

    {% if loop.index0 is divisible by(2) %}
    (entry odd output here)
    {% endif %}

    {% if loop.index is divisible by(2) %}
    (entry even output here)
    {% endif %}

</div>
{% endfor %}

but this just gives me a new row for each entry.
What's the best approach?

I would go with Twigs batch filter, which exactly solves your problem.

Here an an adapted example:

{% set items = craft.entries({
    section: 'events',
    level: 2
}).find() %}

{% for row in items|batch(2, 'No item') %}
    <div class="row">
        {% for item in row %}
            {# Your entry #}
        {% endfor %}
    </div>
{% endfor %}


background-image CSS property: how to do it right with Craft? My current code is:

#header { background-image: url('{{ sitePath }}/assets/toxicomental/header.png'); height: 150px; }

Still, I don't get the image showing.

What do I do wrong?

There is a function called alias that returns a defined alias. A default alias is @web and it represents your base url,

background-image: {{ alias('@web') }}/path/to/image.jpg;

Would display the file image.jpg in web/path/to/


Want to sort a table field from Twig Guess this is a stupid question, but I'm trying to sort a table based on which column the user wants to sort.

Tried:

{% for row in entry.tablefield|sort %} (No effect)

{% for row in entry.tablefield.order('firstName') %} (Error message)

Anyone who know if this is possible or know how to do this?

You can't do that with core Craft functionality or Twig filters, but as Mats already suggested in the comments, you can do it with a plugin like "Super Sort".

The template code to sort the array returned from the table field with that plugin would be:

{% for row in entry.tablefield|supersort('sortAs', '{{ object.firstName }}') %}


How Do I Add a rel="canonical" HTTP Header to Embedded PDF Files? I'm working on project where I would like to directly embed PDFs onto web pages. We'll be using Google's PDF viewer as the embed tool and implementing via a macro.

Here is the macro as it stands now:

{% macro pdfEmbed(pdfLink, width="580", height="480") %}

    <iframe src="https://drive.google.com/viewerng/viewer?embedded=true&url={{ pdfLink }}" width="{{width}}px" height="{{height}}px"></iframe>

{% endmacro %}

For SEO purposes, I'd like to set a rel="canonical" on the PDF to point to the entry on which the PDF is embedded so Google knows to index the parent page and not the PDF. From what I've read, the general best practice for how to do this with embedded PDFs is via HTTP headers. See here for more detail: https://moz.com/blog/how-to-advanced-relcanonical-http-headers

I'm struggling with how to implement it in practice. I think the best method would be to use {% header %} tag within the macro but I'm not sure if there's a way to target that at just PDF files? If that doesn't work, .htaccess could be an option but then I lose the ability to dynamically set the canonical on the PDF based on the URL of the entry that houses the PDF.

What is the best way to do this in Craft? I’m running a Craft 3 site FYI.

Thanks!

So the problem you're running into is all about context. Twig operates in the context of the http request for the parent page; so any headers you add via Twig will be added to the page http header, which is not what you want.

This could be done server-side, as the article you reference mentions. But it becomes a bit more involved when we're dealing with dynamic content, which presumably we are if a CMS is in the mix.

Because what you need is something that will intercept the http requests for documents you want to affect the header of, and then set it based on the dynamic page where it's coming from.

You could accomplish this via a plugin by writing a controller that sets the headers and then returns the actual file. Then in your Twig code, you'd link to the controller not the PDF file.

If you're using SEOmatic for Craft CMS 3, you can use the built in seomatic.helper.seoFileLink() function to do all of this for you.


Twitter, Dukt OAuth, and Placid error Trying to get Placid working but I can't get Twitter to Connect. The keys are all set correctly, but when I click 'Connect', I get this error:

Craft\OauthService and its behaviors do not have a method or closure named "encodeToken".

On line 266 of /home/rizen/sites/rizencreative.com/craft/app/framework/base/CComponent.php(266)

throw new CException(Yii::t('yii','{class} and its behaviors do not have a method or closure named "{name}".',
    array('{class}'=>get_class($this), '{name}'=>$name)));

@crawf was right with his answer, but I recently saw the preview release for Craft 3, so Placid 2 is going to wait and be written for that.

So I thought I should fix the current version of Placid to work with the latest version of OAuth (currently 0.9.71) and as a brucie bonus you can now connect to more than just the twitter api :)

You can get the latest version (1.3.0) on github and any issues just give us a shout on the repo (or here, whichever you feel most relevant)


Conditionals and outputting tables Need a hand on a conditional to see if my table has any data, and if it does, output the table. The second thing I  need help is the code to output the table. When I look at tutorials, they always seem to output the table as an HTML list. Like:

   {% if block.codePoints | length %}

    {% for row in block.codePoints %}
         {# Assuming 'text' is the column handle of the text field #}

{{ row.text }}

    {% endfor %}

{% endif %}

I can't find an example of:

Thanks.

Assuming your example code, something along these lines will help...

{% if entry.yourTable | length %}

    {% for row in entry.yourTable %}

       {{ row.column1 }}	{{ row.column2 }}	{{ row.column3 }}

    {% endfor %}

{% endif %}

Here's the relevant section in the docs: Table fields


Redirect on front end Password Redirect not working Craft 2.6.2963

I've got a password reset form on the front end which works correctly sending the email. However it doesn't redirect on submit, unless you are loggedin.

redirect works if logged in, but if I'm logged in I wouldn't be resetting my password. How to get the redirect working correctly?

This is my entire form:

<form method="post" accept-charset="UTF-8">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="users/sendPasswordResetEmail">
    <input type="hidden" name="redirect" value="/password-reset-notice">

Username or email

        Email Address
        <input class="form__field form-control" type="text" name="loginName" id="loginName" placeholder="Email Address" value="{% if loginName is defined %}{{ loginName }}{% else %}{{ craft.session.rememberedUsername }}{% endif %}"/>

    {% if errors is defined %}

            {% for error in errors %}

{{ error }}

            {% endfor %}

    {% endif %}

        <input type="text" name="comment" tabindex="-1" class="form__field form__field--comment" />
        <button class="form__submit button button--lg" type="submit">Submit ›</button>

</form>

This issue is caused by the presence of the {% requireLogin %} tag in one of your Craft templates. Remove the tag from the template in question, and the redirect should work as expected.

Craft Docs: https://craftcms.com/docs/templating/requirelogin


Merge list of categories related to 'project' entries - not working, a solution good to be back)
Helping a friend out with a website for his tiling business. The site contains a 'projects' section which displays category-filter buttons allowing the user to toggle relevant projects.
The CMS also contains a custom field to allow my friend to make a project entry 'sticky'.
I had been struggling to make this work:
{# get all sticky Project entries #}
{% set stickyProjects = craft.entries().section('project').limit(30).sticky('1') %}
{% set stickyProjectEntries = stickyProjects.all() %}

{# get all non sticky Project entries #}
{% set projects = craft.entries().section('project').limit(30).sticky('0') %}
{% set projectEntries = projects.all() %}

{# Fetch, then merge, categories related to both sticky and non-sticky Projects #}
{% set stickyCategories = craft.categories.relatedTo({ sourceElement: stickyProjectEntries }).all() %}
{% set nonStickyCategories = craft.categories.relatedTo({ sourceElement: projectEntries }).all() %}

{% set usedCategories = stickyCategories|merge(nonStickyCategories) %}

Even after using the Merge filter, "usedCategories" was outputting a duplicate category "External" (see image)

Instead of using the Merge filter, I tried "Passing Multiple Relation Criteria" from the Craft Docs, replacing "and" with "or", below...
{# get all sticky Project entries #}
{% set stickyProjects = craft.entries().section('project').limit(30).sticky('1') %}
{% set stickyProjectEntries = stickyProjects.all() %}

{# get all non sticky Project entries #}
{% set projects = craft.entries().section('project').limit(30).sticky('0') %}
{% set projectEntries = projects.all() %}

{# Fetch, then merge, categories related to both sticky and non-sticky Projects #}
{% set stickyCategories = craft.categories()
    .relatedTo([
    'or',
    { sourceElement: stickyProjectEntries },
    { sourceElement: projectEntries },
    ])
    .all() %}

{% set usedCategories = stickyCategories %}

Which produced the desired result: (image)

Thanks all, I hope that helps you all.
:)


Add several feeds into an array I'm relatively new to Twig and PHP in general, so please don't shoot me just yet for asking stupid questions!

Basically, I've got several feeds from RSS to Facebook and Twitter. And I need to merge all of these into a custom array so I can make sure all fields match. I'm gonna output all these later, after sorting them by their published date.

But how do I get started with this thing? Create an empty array first, and then loop through the feeds and push each post into the array? How do I name the fields? This is what I have so far:

{% set feeds_array = [] %}

{% set feed = craft.feedme.feed(my_rssfeed) %}

{% for node in feed %}
    {% set feeds_array = {'title': node.title} %}
{% endfor %}

{% for post in feeds_array %}
    {{post}}
{% endfor %}

Is this the way to go about this?

It looks a bit awkward, but to append items to an array you have to use Twig's merge filter, merging the feeds_array with itself for each new item. Here's how I'd do it if you need different logic for each feed:

{% set feeds_array = [] %}

{% for node in craft.feedme.feed(my_rssfeed) %}
    {% set feeds_array = feeds_array|merge([{ title: node.title }]) %}
{% endfor %}

{% for node in craft.feedme.feed(my_otherfeed) %}
    {% set feeds_array = feeds_array|merge([{ title: node.whateverField }]) %}
{% endfor %}

{% for post in feeds_array %}
    {{ post }}
{% endfor %}


Passing data to includes - overrides & defaults I am trying to create a reusable component with a set a default variables that can be overridden when included in a template:

includes/social.twig

{% set padding, size, color, hover = '2', '4', 'pink', 'black' %}

page.twig

{% include '_includes/social-links.twig' with {
  padding: '10',
  size: '2',
  color: 'blue',
} %}

When using this, variables that haven't been set in the include statement would remain as defined in the include file, and those that have would override the variables set in the include file. This doesn't happen - nothing gets overridden.

I can achieve a working version of this using:

includes/social.twig

page.twig

{% set padding, size, color, hover = '2', '2', 'blue', 'black' %}
{{ include('_includes/social-links.twig') }}

This involves not setting the vars in the include file, but setting them in the page template - this approach seems more error prone and less maintainable than the version I am trying to achieve.

There is no reason why your code should work, because any variable declared outside of your include file in the with {...} block will be immediately overwritten by your variable definition (#set) in the beginning of your included file.

What you need to do in your include is to check, if the variable was passed in from the outside, and if not, set it to a default value.

So I guess the best way could be this in your includes/social.twig file:

{% set padding, size, color, hover = padding ?? '2', size ?? '4', color ?? 'pink', hover ?? 'black' %}

The ?? used here is called the null-coalescing operator. It will check if the variable before the ?? is defined (which it is if provided from the outside) and in case it's not not, fall back to the value after it. Have a look here, if you do not know it: https://straightupcraft.com/events/twigs-null-coalescing-operator