What's the best practice for handling data migration and organization across development environments? This issue becomes especially difficult when there are multiple environments, with multiple developers working on different features that affect the data structure.

The holy grail is a git-style distributed database setup, and I believe the Craft team is working on a solution that integrates with Craft Core. But it'd be great to hear how the community is handling this currently.

My general approach for this, not just with Craft, but with all CMSes is to have a shared database for development. It's not the most ideal solution, since there can be overwriting of work, but it at least prevents schema changes from having to be redone across multiple environments.

Once a site goes live, maintaining a dev environment alongside live becomes a bit more troublesome. My approach right now is generally to either make the changes in both places, or make the schema changes on live first and then copy the database back down to dev. (This of course requires that the changes not be anything that will break the current live site, and that both dev and live site are running the same version.)

On the upside, Craft does an awesome job of handling the schema changes that come with Craft updates. Basically the database version is checked against the file version, and the database changes can be reapplied on additional environments to update all the databases. This makes updates across environments lot easier than something like ExpressionEngine, which usually requires a multi-step copying of database down from live and back up to live.

In the future I'd love to see ways to encapsulate configurations in a migration similar to the updates, so that it's really just a matter of running the latest migrations to keep everything in sync.


Plugin settings per site/locale I'm trying to make a plugin in Craft 3 but want it to be possible to set different settings for each separate site or locale. How would I go about doing this?

Edit

OP updated the question to specify Craft 3, so this is no longer relevant.

You can define a separate value for each locale, as described in the localisation documentation:

<?php

return [
    'flagName' => [
        'de' => 'Bundesflagge',
        'fr' => 'Tricolore',
    ],
];


What is the correct way to update a production site with composer? I disable admin updates on production sites, and update Craft and its plugins by updating in the development environment, and then deploying to production using Git.
My basic process starts like this:

Update Craft/Plugins in the development environment
Commit updated composer.json and composer.lock
On production, pull changes from Git
Run composer install

What additional steps are necessary to ensure that the production site is updated correctly?
I'm aware that we still have to run:

./craft project-config/apply
./craft migrate/up

Should we also run these commands?

./craft clear-caches/all
./craft queue/run

Are there any other commands that should be run to help ensure a smooth update? Also, what is the correct order to run them in?
Thanks!

Updating Craft on the production server
Assuming the up-to-date composer file was committed and pushed to the repository:
cd /path/to/repo

# Removes any changes that would block the pull and then pulls from master (or your branch name of choice)
git reset HEAD --hard
git pull origin master

composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader

# Depending on the actual server, reload the PHP FPM service to clear the cache
service php7.4-fpm reload

# This one does a backup by default
./craft migrate/all

./craft project-config/apply

# Watch out here, because probably not all caches should be cleared: Imagine all image transforms are gone, not great.
./craft clear-caches/all

Updating Craft in the development environment
This part is covered by the docs: Updating from the terminal
To queue or not to queue
In most cases it is not necessary to touch the queue system, since it relies on Control Panel visits. Here is some more info: Queues


How do I get the Site/Revision/Draft in a field in the control panel? Is there an easy way to fetch the selected Site, Revision and Draft of the dropdown (the one an editor would use to switch the Site/Revision/Draft) in control panel in a plugin?

The only way I found so far is to get it from the provided URL parameters. This works but I don't feel very safe using it and it won't work in any CLI script, because of the missing Request.

In the context of the Control Panel, the URL parameters are the best way to get that info because the user chooses which site to work on, which draft to work on, or which revision to review. Craft, itself, relies on those URL parameters.

In the context of a CLI request, there is no user interaction. You're on the hook to sort out which entry, draft, site, and user are relevant to the element you'd like to manipulate. As of Craft 3.3 (current version today) there is an EntryRevisions service class. All of the methods are deprecated in favor of running your own entry queries, but those methods are a good reference for how to get the drafts or revisions you're looking for.

For example, rather than running the deprecated method:

$drafts = Craft::$app->getEntriesRevisions()->getDraftsByEntryId($entryId, $siteId);

You'd run the contents of that method for yourself:

return Entry::find()
    ->draftOf($entryId)
    ->siteId($siteId)
    ->orderBy(['drafts.name' => SORT_ASC])
    ->all();


Craft 3 Admin not loading cpresources files over HTTPS I have a Craft 3 install on my client's Windows machine running Apache, PHP and MySQL.

We purchased an SSL certificate but the main Admin login page (on SSL) keeps loading cpresources assets over HTTP which cause all of these CSS and JS assets to be blocked by the browser.  However, loading these assets over https in a browser works fine.

The Site URL is indeed set to https.  I've tried to force change the URL in config/general.php using the siteUrl and baseCpUrl parameters.  I've also tried clearing Craft's cache and removed the www/storage/* and web/cpresources/* content but nothing works.

I don't have a https redirect in .htaccess as I believe the force redirect was set up when the SSL was installed (I don't have how this step was done).

Does anyone know how to solve this?  The admin page is totally broken and unusable at the moment.

While the server setup is different, this issue might be related to the below.  However I wasn't able to solve my problem based on it.
Craft Admin assets do not load over https (Apache & Cloudflare)

The fix was to delete the content of the /cpresources folder and that did the trick.


Adding additional attributes to modifyEntryTableAttributes() Using the example code from the docs, I'm attempting to add a value from my custom field to the Entries listing.

public function modifyEntryTableAttributes(&$attributes, $source)
{
    if ($source == 'index')
    {
        unset($attributes['expiryDate']);
        $attributes['id'] = Craft::t('ID');
    }
}

How do I go about accessing additional attributes on the Entries? The custom field data is stored in MyPluginName's table and doesn't appear to be available in the attributes of the EntryElement.

Thanks for any pointers you may have!

See this question:

  Possible to add category field to modifyEntryTableAttributes?

Basically, you need to use the getEntryTableAttributeHtml hook to get the actual content to the table cells in addition to the modifyEntryTableAttributes. You can do queries here if you need to get the data if you can not access it from the entry.

public function modifyEntryTableAttributes(&$attributes, $source)
{
    if ($source == 'index')
    {
        // This will be the header name of the column, the <th>
        $attributes['myCustomField'] = Craft::t('My Label');
    }
}

public function getEntryTableAttributeHtml(EntryModel $entry, $attribute)
{
    if ($attribute == 'myCustomField')
    {
        // Fetch the related data from your plugin. This will be placed in the <td>'s
        $fieldData = craft()->myPlugin->getFieldData($entry);
        // OR $entry->myCustomField->first(); if myCustomField is an ElementCriteriaModel.
        return $fieldData;
    }
}

EDIT: Think of it this way: when craft is loading up the entries (or any of the element types) to display on the index page, it has to know what fields are going to show. These fields are defined in the EntryElementType::defineTableAttributes. This method returns an array of attributes, where the key is whatever you want, and the value is what is displayed in the tables <th> tags. In this function, the entry type is defining some standard fields to show (title, uri, postdate etc), but Craft is nice enough to let plugins modify this array before it is returned.

Where does the array of attributes go after? The function for populating the <td> tags of the table, the EntryElementType::getTableAttributeHtml($entry, $attribute). The first thing this function does it to let plugins decide what to do, so it calls the getEntryTableAttributeHtml which is the function you should implement. The $attribute parameter is the key you defined. Here you have a chance to tell Craft how the data is displayed. If you in the first function defined $attributes['id'] and did nothing in the second function, the default way Craft is getting this data is doing $entry->$attribute (or $entry->id in this case), which would display the entry's id in the column. If $entry->$attribute is an array, or an object without a __toString, this will not work, so you will have to tell Craft explicitly how to represent this field, e.g.

if ($attribute = 'myArrayOfSpecialFields'){
  return $entry->myArrayOfSpecialFields['indexOfStringToDisplay'];
}

There are tons of useful information on this in the EntryElementType, you can just follow the flow in the code (perhaps start in the ElementIndexController)

Hope that makes things more clear


Craft Commerce - More detailed reporting I'm looking to get more detailed reporting from craft commerce. I would like to be able to see a breakdown of what we've sold in a set period of time (week, month etc) which details out products, revenue, and quantities. Right now I only have the option to see total revenue or top products

Select the date range of your orders:

Then export the line items to csv and open in excel:

You can then use excel to create sums/grouping and charts etc.


Get all Entries by Matrix Lightswitch I would like to fetch all entries in a section according to a Lightswitch value inside of a matrix field. Initially I tried:

craft.entries.section('buildings').spaces.space.isAvailable('1').find

but this doesn't pull any results. Is this even possible in a single query? Or do I need to get all entries from the section first, and then loop over them in order to determine if the Lightswitch has the desired value?

Fetching entries by a Matrix block field value is actually quite complicated, and not possible to do in a single query – at least not using built in services like craft.entries.

Your idea of pulling all entries and looping through would work – but this kind of "brute force" solution might not scale that well, performance wise.

A better idea might be to first pull all the space Matrix blocks that have a true value for the isAvailable field, and then pull any entry belonging to the buildings section that has a relation at least one of those blocks.

Unfortunately, unlike the EntriesService (i.e. craft.entries), Craft doesn't expose the MatrixService to Twig, making the above hard to accomplish in a template.

For a clean & effective solution to this problem, I'd look to the excellent Low Blocks plugin.

With Low Blocks, you'll be able to pull all space blocks with a true value for isAvailable like this:

{% set spacesMatrixField = craft.fields.getFieldByHandle('spaces') %}
{% set spaceMatrixBlocks = craft.lowblocks.blocks.fieldId(spacesMatrixField.id).type('space').isAvailable('1') %}

After that, we can loop on the matrixBlocks variable in order to create an array containing the IDs of the entries "owning" these Matrix blocks:

{% set buildingEntryIds = [] %}
{% for block in spaceMatrixBlocks %}
    {% set buildingEntryIds = buildingEntryIds|merge([block.owner.id]) %}
{% endfor %}

And finally, we pull the entries using the buildingEntryIds array variable as the parameter to the id argument:

{% set entries = craft.entries.section('buildings').id(buildingEntryIds).limit(null) %}

Here's everything together, for cohesion:

{# Get Matrix blocks #}
{% set spacesMatrixField = craft.fields.getFieldByHandle('spaces') %}
{% set spaceMatrixBlocks = craft.lowblocks.blocks.fieldId(spacesMatrixField.id).type('space').isAvailable('1') %}

{# Get entry IDs #}
{% set buildingEntryIds = [] %}
{% for block in spaceMatrixBlocks %}
    {% set buildingEntryIds = buildingEntryIds|merge([block.owner.id]) %}
{% endfor %}

{# Get entries #}
{% set entries = craft.entries.section('buildings').id(buildingEntryIds).limit(null) %}

That should hopefully do the trick. If you're interested though, here's some more info on why your first attempt wouldn't work:

First, I'd like to point out that its important to realize that each chained "segment" (such as section or isAvailable) in a call to craft.entries in a template actually ends up as an attribute of an ElementCriteriaModel (an object Craft constructs to query the database). This means that

craft.entries.section('buildings').spaces.space.isAvailable('1').find

is actually the same as

craft.entries({
    section : 'buildings',
    spaces : null,
    space : null,
    isAvailable : '1'
})

It should be fairly obvious why this query won't do what you want; Craft has no idea that spaces.space.isAvailable is actually the "path" to a certain Matrix block type's field, and will consider each of those segments (spaces, space and isAvailable) as a separate attribute/argument.

Aside from the syntax issue, the real reason why you'll never be able to use something like spaces.space.isAvailable in a craft.entries query is that Matrix blocks aren't just regular, nested fields, but elements unto themselves (just like entries, categories or assets). Also, for any single entry there can be an indefinite number of instances of each block type. If you have multiple space blocks for a single entry, some with a false isAvailable value and some with true, how would Craft know if the entry should be returned or not?


Is there a JavaScript event available for when the parent tab of a custom field is shown? I need to have a JavaScript event that is triggered when the parent tab of my field type instance is shown on the entry form. So if the field is on the second tab, the div is hidden on instantiation. The div is obviously shown once the parent tab is clicked. I need this event to reset the map in my field type. If a map is instantiated with a hidden div, it must be redrawn before it can be displayed properly. So when the div displays (after the parent tab click) I need to trigger the method to redraw the map. Is there a JavaScript event available for this and if so, how would I use it?

If no such event exists and if one can't be added, I guess the only other way would be to try to traverse the DOM and add click events to the respective tabs. This feels kind of like a hack though and would break if the DOM changes.

There is not, however if you have a Javascript class that extends Garnish.Base, you will be able to listen for a custom resize event on your container div using Garnish.Base::addListener(), which will trigger when the element first gets a height.

window.MyClass = Garnish.Base.extend(
{
    container: null,

    init: function(container)
    {
        this.$container = $(container);

        // Is the container already visible?
        if (this.$container.height())
        {
            this.doStuff();
        }
        else
        {
            // Hold off until it is
            this.addListener(this.$container, 'resize', function(ev)
            {
                this.removeListener(this.$container, 'resize');
                this.doStuff();
            }
        }
    },

    doStuff: function()
    {
        // this.$container is visible now
        // ...
    }
});

Off-topic, but worth noting: one of the benefits of using Garnish.Base::addListener() rather than jQuery.on() or jQuery.bind() is that it will maintain the scope for you in the callback function. So you don’t need to worry about doing that yourself with jQuery.proxy(), e.g.

this.$container.bind('click', $.proxy(function(ev)
{
    // `this` would refer to the container element here, if it weren’t for $.proxy().
}, this);


Assets count conditional I have a simple question about Assets. I want to output some HTML around a set of image IF there is more than one image. If there is just one image I would output different HTML. I know how to do this easily within EE's Assets but not sure how to do it in Craft's Assets.

In EE I would use something like:

{if photo:total_files > "1"}

{if:else}

{/if}

I think I could target the first image but not sure how to construct the full conditional.

{% if entry.photos | length %}

{% set image = entry.assetFieldHandle.first() %}

{% endif %}

You're close!

{% set numberOfPhotos = entry.photos|length %}

{% if numberOfPhotos > 1 %}
  {# more than one #}
{% elseif numberOfPhotos == 1 %}
  {# exactly one #}
{% else %}
  {# no photos (always handle this case...) #}
{% endif %}


Getting $craftPath error on server trying to get Craft running Trying to get my Craft site running on my server for the first time.

Getting the error Could not find your craft/ folder. Please ensure that $craftPath is set correctly in /var/www/dev.mysite.com/htdocs/public/index.php

However, there is nothing different to the folder structure on my server than I have locally.
i.e. the $craftPath set in index.php is still ../craft which is correct... my Craft folder sits beside my public folder as per default installation.

What can I try to get this working?

9 times out of 10, if you're absolutely sure the path is correct, it's either a permissions issue (PHP doesn't have permissions to open the craft folder) or your php.ini file has  open_basedir restrictions in place preventing PHP from accessing the folder.


Imperavi Article (WYSIWYG editor) Any plans on adding Imperavi's Article WYSIWYG editor to Craft CMS, like Redactor?

I asked the same question ( Oct 24 2019 ) to the Craft team, so i'll just copy & paste the answer here from Brandon Kelly (Pixel & Tonic):

  Hey Christopher,

  We do have plans for a field type like that, but more likely based on
  editor.js rather than Imperavi's Article Editor.

  I have heard rumblings that someone else is working on a plugin based
  on that though.

  -Brandon


How to tell whether a SuperTable column has data or is empty? I have a "contact table" SuperTable with columns for Name, Phone, Email, and Website. In the template, I'm displaying the data as a table.

I only want to generate table columns if a column has data. For example, if there are no Phone Numbers included, I don't want a Phone column. If even one row has a phone number, I do want to include that column.

How do I create a conditional to check whether a SuperTable column has data in it?

This might be related to Querying a supertable field.

I forget who solved this for me! I think it was Michael van Dorth.

      {# Caption #}
      {% if block.caption %}

{{ block.caption }}

      {% endif %}

      {# Setup #}
      {% set rows = block.contactTable.all() %}
      {% set phoneRows = 0 %}
      {% set emailRows = 0 %}
      {% set websiteRows = 0 %}

      {% for row in rows %}
        {% if row.phone != '' %}
          {% set phoneRows = phoneRows + 1 %}
        {% endif %}
        {% if row.email != '' %}
          {% set emailRows = emailRows + 1 %}
        {% endif %}
        {% if row.website != '' %}
          {% set websiteRows = websiteRows + 1 %}
        {% endif %}
      {% endfor %}

      {# Headings #}

          Name
          {% if phoneRows > 0 %}Phone	{% endif %}
          {% if emailRows > 0 %}Email	{% endif %}
          {% if websiteRows > 0 %}Website	{% endif %}

      {# Body #}

        {% for row in block.contactTable.all() %}

            {{ row.contactName }}

            {% if phoneRows > 0 %}
              {% if row.phone|length %}{{ row.phone.link }}{% endif %}
            {% endif %}

            {% if emailRows > 0 %}
              {% if row.email|length %}
                Email
              {% endif %}
            {% endif %}

            {% if websiteRows > 0 %}
              {% if row.website|length %}
                Website
              {% endif %}
            {% endif %}

        {% endfor %}


How can I display entry edit history on the front end? When editing an entry from the control panel you can switch versions of the entry. I would like to do the same thing but on the front end. Is there any way to do this using native craft functionality or do I need to use a plugin.

Something like this might work.

{% if not craft.request.isAjax %}

    {% set versions = craft.entryRevisions.getVersionsByEntryId(entry.id, entry.locale) %}

    Versions:
    <select class="js-versions-dropdown">
        <option value="">Current</option>
        {% for versionEntry in versions %}
            <option value="{{ versionEntry.versionId }}">Version {{ loop.index }} ({{ versionEntry.postDate|date('m-d-Y') }} )</option>
        {% endfor %}
    </select>

{% endif %}

{% if craft.request.isAjax %}

    {% if craft.request.param('versionid') %}
        {% set entry = craft.entryRevisions.getVersionById(craft.request.param('versionid')) %}
    {% endif %}

{% endif %}

<div>
    {{ entry.title }}
    ...
</div>

In this example, you would want to listen for an onChange event on the dropdown list and reload the template via ajax, passing the 'versionid' as a post variable. Alternatively you could also just reload the whole page, in which case remove the 'if ajax' stuff. In this case, you'll probably also need to add some logic to the drop-down list so as to display the correct 'selected' option in the list.


Using Date to Filter Entries I am trying to pull entries that match a date criteria. Any ideas why this is not working?

{% set entries = craft.entries({
section: 'leads',
lastAssigned: '("now"|date_modify("-3 days"))'
}) %}

I get the following error.

Fatal error: Call to a member function getTimestamp() on a non-object in .../craft/app/helpers/DbHelper.php on line 597

I believe it's the quotes that is throwing it off. Try this:

{% set entries = craft.entries({
section: 'leads',
lastAssigned: now | date_modify("-3 days")
}) %}


Questions about Craft 4 release and licenses Being busy rethinking an existing website to rebuild in Craft I just found out Craft 4 was announced september last year. Some of the new features, like nestable Matrix fields in particular, are very welcome and chances are I'd rather wait for Craft 4 to come out to convert a big amount of data to the new CMS than to rebuild the website in Craft 3 to have another data-migration(/rebuild?) for new fields etc. in Craft 4 later.

So I'm having the following questions:

1) Is there anything to say about a release date for Craft 4? And about around what time Pixel and Tonic consider it a stable release to be used in production?

2) What will happen to the support and updates for Craft 3 once Craft 4 is out? Is there any roadmap showing support/update-cycles for Pixel and Tonic products?

3) Will Craft 3 work with the announced Craft Cloud or will the cloud only work from version 4 up?

4) Is there anything to say about how difficult it will likely be to migrate from v3 to v4 and what that would be about?

5) What about existing paid licenses when a customer upgrades from version 3 to 4? Is it under the same license after the upgrade? Or are licenses bound to a major version and need a customer buy a new license for version 4?

Thanks in advance!

1) Is there anything to say about a release date for Craft 4? And about around what time Pixel and Tonic consider it a stable release to be used in production?

Nothing official on either.

  2) What will happen to the support and updates for Craft 3 once Craft 4 is out? Is there any roadmap showing support/update-cycles for Pixel and Tonic products?

No official dates yet, but you can probably use past support timelines (https://craftcms.com/guides/supported-versions) as a guide to what Craft 3 support would be once Craft 4 is out.

  3) Will Craft 3 work with the announced Craft Cloud or will the cloud only work from version 4 up?

Nothing officially announced.

  4) Is there anything to say about how difficult it will likely be to migrate from v3 to v4 and what that would be about?

We'll try to make the 3 => 4 migration as seamless as possible.

  5) What about existing paid licenses when a customer upgrades from version 3 to 4? Is it under the same license after the upgrade? Or are licenses bound to a major version and need a customer buy a new license for version 4?

The licensing model should be exactly how it is for Craft 3.


console.groupCollapsed("Application Log"); - what is it? If I "View source" in my browser I get a bunch of stuff in the end of my html output. It starts with console.groupCollapsed("Application Log");.

I guess this is something Craft does automatically. Is it possible to turn it off when I launch my site?

This is something Craft only shows if your site is in devMode (http://buildwithcraft.com/help/dev-mode).

If you use Firebug or Chrome Developer Tools for instance, it shows you a performance and error log.

By disabling devMode, it disappears. Do this by setting 'devMode' => false into your craft/config/general.php.


Commerce Order Status History I am trying to bring some of the order status history from my clients commerce shop orders into a web page. I seem to be able to get the Current/Previous Status (prevStatus/newStatus.name), but cannot seem to get the elements in the attached image - 'Updated By' and 'Date'.
I have tried a few different tags e.g. 'order.orderStatus.date|datetime' but they just seem to update the the time 'now' rather than the time of the order status change.
Its probably an obvious answer but i cant find this tag to output-  if anyone can help that would be great
Thanks
Malcolm

Try
{% set recentHistory = order.histories|first %} // get the first order history item
{{ recentHistory.dateCreated|date ?? 'no history record' }}

there is no date attribute on an order history model, just the dateCreated. So in effect you are passing null to the |date filter which will default to the current time/date.
You were trying to access the current order status model on the order. There is no dateCreated on the order status model, only the model itself. The date the order status was applied is in the orderHistory models.


Problems setting up a local site I am running into problems with virtual hosts while trying to run Craft locally.
My setup was working perfectly and after a restart of my mac I get error messages and I don't understand why.

I am using Mamp to run Apache and MySQL.
When I am going to one of my virtual host url I get the following error:

And when I type 'localhost' I get the following:

I have double checked the httpd.conf and the virtual hosts is enabled and my httpd-vhosts.conf is set up correctly as well.

I assume there is a certain issue with the virtual hosts as but I just cannot figure it out and it stop working without any changes/updates form my side so I'm really loosing it...

Does any one has an idea where to start searching for the problem?

You can't use the domain .dev anymore, it's Google's gTLD (https://icannwiki.org/.dev) and they don't want to share. See https://medium.engineering/use-a-dev-domain-not-anymore-95219778e6fd for a detailed backstory.

Instead, you should use the TLDs reserved by the IETF for this purpose, like .test.

For reference, this is the HSTS List maintained by Chromium which is in turn the basis for the lists used by Firefox, Opera, Safari, Internet Explorer and Edge


Show field handles on control panel As someone relatively new to Craft I'm constantly switching between a content type and /admin/settings/fields so that I can see the handles for that content type. It just occurred to me that it would be relatively simple to show the handle right next to the field's name on the edit content screen. Might there be a setting for this somewhere, or would I have to (or be able to) create a plugin to do this?

In case it's unclear, I'm looking to turn this

into this

There's a plugin called CP Field Links which will display field handles and provide easy access to field (and entry type) settings. Please note that the plugin requires devMode to be enabled.

I'm the plugin author, so just get in touch if you have any questions or spot any issues.


nofollow option for rich texts Is there a way to add an nofollow option to the rich text editor? Just like new window option.
The only thing I found is a Redactor config to make all links nofollow. But I need it optional per link.

There's nothing native in Craft that would allow you do to that.

Should be possible via a Craft and Redactor custom plugin, though, I'd guess.


How do I cycle a class on a Matrix block? I am trying to add a class which will cycle through on every iteration of a matrix block type, here is my code:

{% for block in entry.asideNavigation %}

    {% switch block.type %}

        {% case 'textBlock' %}
            <li class="aside__nav__item {{ cycle(['cs-a','cs-b'], loop.index0) }}">
                ...
            </li>

        {% case 'imageBlock' %}
            ...

    {% endswitch %}

{% endfor %}

This cycle function gives me the error "Variable "loop" does not exist" where am I going wrong?

This is mostly likely a scoping issue inside the switch statement.  Try something like this:

{% for block in entry.asideNavigation %}

    {% set index0 = loop.index0 %}

    {% switch block.type %}

        {% case 'textBlock' %}
            <li class="aside__nav__item {{ cycle(['cs-a','cs-b'], index0) }}">
                ...
            </li>

        {% case 'imageBlock' %}
            ...

    {% endswitch %}

{% endfor %}


How to check for a value OR NULL on custom enddate field using yii syntax when calling entries? I have a section of 'deals/coupons' with custom startDate and endDate.  These are needed so the client can load up a bunch of deals but only have them render to the page when a particular deal is 'active'.

The below syntax works to not show any deal before it's startdate has passed:

{% paginate craft.entries({
   section : 'dealDirectory',
   limit   : pageSize,
   startDate : '<=' ~ now
}) as pageInfo, dealEntries %}

And using the below code I can prevent deals from showing after their enddate but only if enddate has data:

{% paginate craft.entries({
   section : 'dealDirectory',
   limit   : pageSize,
   startDate : '<=' ~ now
   endDate : '>=' ~ now
}) as pageInfo, dealEntries %}

If enddate does not have a value it eliminates those entries from showing.  I need to find a way to check if enddate is greater than now OR is null so that it will continue to show deals that do not have an enddate. Such as:

{% paginate craft.entries({
   section : 'dealDirectory',
   limit   : pageSize,
   startDate : '<=' ~ now
   endDate   : '>= ' ~ now ~ 'or is null'  // but this syntax incorrect
}) as pageInfo, dealEntries %}

I'm having a hard time finding a reference for this type of markup.

Shooting in the dark here, but looking off this ticket and the ECM parameter value syntax in the docs, could you do something like:

{% paginate craft.entries({
    section : 'dealDirectory',
    limit   : pageSize,
    startDate : '<=' ~ now
    endDate: 'or', '>= ' ~ now, 'not null'
}) as pageInfo, dealEntries %}

The or is a total guess based on the and in the other ticket.


I just can't get FeedMe to work I am trying to use the FeedMe plugin to append data to existing entries.

My existing entries have a field that is a unique ID.  It is named Line Id.   They also have a blank field named Program Justification.

The .csv file I am importing has only 2 fields Line Id and Program Justification.   They should sync with the existing entries.  But, FeedMe keeps throwing an error

*justAPAF Justification: Unable to match an existing element. Have you set a unique identifier for ["lineId"] and does this have a value? - Element.php:104*

I do not know what I am doing wrong.  I use Line Id as a unique identifier in multiple database, data parsing and data visualization tools with no issues.

I am sure this is a simple 30 second explanation - but it has stopped me cold in my tracks for 5 days now.

Thanks

I believe we figured this out over Slack, but the issue here was that you need to actually import your Line Id column into your lineId field, otherwise Feed Me doesn't know anything about that.

The checkbox to tell Feed Me to use a certain field's value to match existing elements on is one half of the problem - you've already correctly chosen Line Id. The issue is you need the other half - what data in your feed is supposed to match up with Line Id and lineId.

I suppose a less confusing UI would be to have an accompanying dropdown field near those checkboxes to say which bit of data in your feed should you be comparing with.


Route / to specific template I'm trying to route the homepage / to a specific template. In my routes.php file, i've tried these two without result:

return array(
    '/' => 'specific/_entry',
    '' => 'specific/_entry',
);

A site's home page is routed via a special route __home__. I don't believe you can set that in routes.php, but it's worth a shot. Generally, you specify a Single as the homepage, and can set the template there. It defaults to index.


Limiting image rows by 5 but an unknown number of section entries I'm trying to limit the total number of images shown to 5. The below clearly isn't correct but gives a rough idea of what i want to do.

One entry could contain 1 image and the next entry 3 images. So i can't set a limit on the craft.entries tag because of the unknown number of images in an entry. It's on the images for loop i want to limit to 5.

{% for images in craft.entries.section('pages').type('events').order('eventDate desc').eventDate('<=' ~ now).search('gallery:*') %}
    {% for image in images.gallery.limit(5) %}

    {% endfor %}

{% endfor %}

Something like this should work:

{% for images in craft.entries.section('pages').type('events').order('eventDate desc').eventDate('<=' ~ now).search('gallery:*') %}

    {% set image_set = images.gallery %}
    {% for i in 0..4 %}
        {% if image_set[i] is defined %}

        {% endif %}
    {% endfor %}
{% endfor %}


Retrieving Checkbox Values from Plugin I have a checkbox field that is populate with user choices.  I need to get the values they have selected from within a plugin. Here is my attempt. Not working.

    $entry  = craft()->entries->getEntryById($entryId, $localeId = null);
    foreach ($entry->storyCategories->options as $option) {
     var_dump($option);
    }

Can somebody please show me how to get these selected values?

You can pull an array of all the options for a checkbox field by calling getOptions():

$options = $entry->storyCategories->getOptions();

Each option will be an object with three properties, label, value and selected. To get all selected options for a field, you can loop through the options and test for the selected property:

$options = $entry->storyCategories->getOptions();
$selectedOptions = array();
foreach ( $options as $option ) {
    if ( $option->selected ) {
        $selectedOptions[] = $option;
    }
}

Note that this exact code will work for Dropdown, Multi-select and Radio button fields as well.


Nested Matrix functionality for one block type using Tags I have an entry with two matrix fields and I want to use relations between them using Tags to create a fake nested Matrix functionality for one block type. The "main" matrix field is for creating a typical banded page (several horisontal stripes of content). One of the blocks in this main matrix has to contain a contentSlider, and since in this specific case adding an Assets field is not sufficient we have to nest or merge two matrix fields.

While looping through the main matrix field using the Switch method I have a block type named "contentSlider". In this block type I have a Tags field named "showTags". In my second matrix field named "slidesMatrix" I have a field named "tags". I want to find blocks in the second matrix (slidesMatrix) related to the current block in the main matrix.

Here is my attempt, it is not giving me any errors but it is not outputting the "slide.heading" field either so something must be wrong:

{% case "contentSlider" %}
    {% set tagsToFind = block.showTags %}
    {% set relatedSlides = entry.slidesMatrix.tags.relatedTo(tagsToFind).order('score').find() %}
    {% for slide in relatedSlides %}
        Matched Tag in: {{ slide.heading }}

    {% endfor %}

This alternative code works, but it is only matching the first Tag from the current block to all the Tags in the second matrix block (slidesMatrix.tags) and switching to one of the native Craft methods like "relatedTo" would be a more powerful solution.

{% case "contentSlider" %}
    {% set tagsToFind = block.showTags %}
    {% set tagToFind = tagsToFind.first.title %}
    {% for slide in entry.slidesMatrix if tagToFind in slide.tags %}
        Matched Tag in: {{ slide.heading }}

    {% endfor %}

To sum this up into one question;
How can I loop through a matrix field filtered by Tags contained in a tags fields inside the matrix blocks I want to loop through, using a native Craft feature like 'relatedTo'?

I just tried to replicate your setup (in simplified form), because I thought this is in fact an interesting and creative approach
to do Matrix nesting that might come handy.

Here's my code that works great for me. I hope it helps, even though I actually don't see the difference to what you have?!

{# Go through our Main Matrix blocks #}
{% for block in entry.mainMatrix.type('mainRelationsBlock') %}

    {# Get the tags selected in the Main Matrix block #}
    {% set tagsToFind = block.mainTags %}

    {# Try filtering Matrix blocks of our Sub Matrix using `relatedTo` #}
    {% set relatedBlocks = entry.subMatrix.relatedTo({
        targetElement: tagsToFind
    }) %}

    {# Show them #}
    {% for relatedBlock in relatedBlocks %}
        <li>{{ relatedBlock.text }}</li>
    {% endfor %}

{% endfor %}


Is it possible to skip Craft Installer through command line or something similar? I´m trying to automate the installation process of Craft as far as possible.
So my question is the following:

Is there a way to automate the Craft installer (the one with the monkey), possibly through a config file or through the command line or whatever. Of course there are possible solutions using headless browsers, but I think that would be too much of an effort for that task.

I´m really looking forward to your replies!

Thanks in advance and cheers!

Ferdi

There are several ways you could approach this.  There is a bash script that automates downloading the latest version of Craft, but it doesn't do the actual installation.

What I would do is create a PHP script that used prompted to accept Craft's license agreement, then used cURL/wget to download and extract the files.  You could prompt for all the information you need for installation (username, password, database, database connection info, etc.), then the script would load Craft's craft/app/bootstrap.php and call Craft's InstallService->run() method passing in the necessary values similar to how Craft's craft/app/controller/InstallController does.


Maintaining and deploying many multi-site from a single codebase We're developing an application that uses a multi-site Craft back-end with a JS front-end, making use of GraphQL. The intention is to maintain a single codebase that can be used to deploy new and update existing instances of the application.
Each client has their own installation of Craft (currently Craft 3.5), with multiple sites in each. To illustrate:
Client A:

site 1, clienta.ourdomain.com/someslug
site 2, clienta.ourdomain.com/anotherslug

Client B:

site 1, clientb.ourdomain.com/customslug
site 2, clientb.ourdomain.com/orangeslug
site 3, clientb.ourdomain.com/frenchslug

Client C:

site 1, clientc.ourdomain.com/potatoes

...etc
The underlying Craft components (i.e. fields, sections, entry types, plugins, etc.) are identical across clients. Initially, I thought that project-config would be all over this until I realised that site data is held in Project Config. With each client having a different number of sites with different slugs etc., that rules out keeping project config in a single git repository.
This, therefore, presents a maintenance and deployment nightmare. As it stands, the only (terrible) option as I see it is:

Create some kind of baseline config and store a matching SQL dump with it
Remove project config from the repo
Manually create migrations for any subsequent modifications.

I had considered forks of the main repo for each Client but again, if there's any project config in those, there's the potential to hose a client's site by modifying site-related data.
The ideal solution would be the ability to configure (!) project config, such that it ignores anything to do with sites. As far as I can see from the generated yaml, sites are only referenced in defining the site itself, and sections' site settings. Configuring the latter programmatically when a site is created is fairly straightforward.
If anyone has any experience of a similar setup, I'd very much appreciate the benefit of their experience.

Craft's Project config is really made for updating changes from staging to production.
When it comes to making changes across a fleet of (different) sites, you're somewhat on your own there. You might think of all of your sites as the same but Craft is thinking of each site independently because that's how it's designed.
It sounds to me that one way to handle this might be to try to automate migrations between installs? You change one site, test it, and then move the migration to the next client site/grouping.
After all, if you're changing or adding fields, for example,  you're most likely going to be changing the (GraphQL) code that also queries those fields as well or everything is going to fall down pretty quick.
Something like Migration Assistant could useful here?
Also, I'm not sure how your devops is setup but theoretically you could share code between installs (same templates, plugins, etc.) The vendor, migrations,  templates, and other code  directories could be symlinked in from a central spot so when they get updated, the rest of the sites get updated as well. Once the build process is complete you could fire off a craft migrate/up command line that propagates across each install to make sure everything updates.


How to debug or log some special variables in Craft CMS? (Especially in a controller) I am going to debug the variables in controller files.

But I couldn't figure out how I can debug it and show the values into front-end site or in log files.

Do you have any ideas about this?

What is your debug mode which you often use when you work in a controller?

You could use for example the dd() method with the craft3-dumper package.
You can also use the debug toolbar.
You could also use Sentry to get a nice overview about your errors with the craft sentry package.
Or you could use xdebug. Or or or ... :)

So there are severals ways to debug something.


Global Cache Working too well? I have a long entry list of authors and I am using global cache to help with the page load, but this global cache prevents the if statement from adding selected to the appropriate option. When I remove the global cache everything performs as intended.

<select name="filter-by-author" onchange="window.location.href=this.value;">
    <option value="/blog">All Authors</option>
        {% cache globally %}
            {% nav author in craft.users({ group: 'blogAuthors', order: 'firstName', limit: null }) %}
                <option value="{{ url('blog/author/'~author.username) }}"
                {% if craft.request.getLastSegment() == author.username %}selected{% endif %}>
                {{ author.name | title }}
                </option>
            {% endnav %}
        {% endcache %}
</select>

This is exactly what caching is supposed to do... flatten the Twig code down to basic HTML, and serve that up instead of dynamically rendering it. Using globally means that the HTML would be identical on every page, which is not really what you want here.

Get rid of globally, so it can cache separately for each page. Since the URL is supposed to affect how that snippet is rendered, you don't want to cache globally.


Auto generation of localised slug When an entry is created and saved in a locale the corresponding entry is created for other locales using the original title. However, when the title of the locale which needs translating is edited the slug isn't auto generated from the new localised title and remains in the original language.

Of course, the slug can be manually edited but unfortunately the likelihood is that users won't bother, or forget, meaning that the urls for entries won't be localised.

What would be ideal is that on the first edit of the localised version that the slug is auto generated from the title as it is for the initial entry. Is this possible either via a plugin or could it be considered in a future version?

Yes, it's possible with a plugin.
Make it listen to onBeforeSaveEntry events and look up how often the entry was already saved by counting entry versions using the getVersionsByEntryId method.
If it is the entry's second save (one version exists) overwrite the slug with an empty string (will generate a new slug from the title).

You should add another conditional to only make it generate a new slug for all locales but the one you first saved in (not exactly sure how to get this), but this should get you started:

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

    craft()->on('entries.onBeforeSaveEntry', function(Event $event)
    {
        $entry = $event->params['entry'];

        if ($entry->id)
        {
            $versionsCount = count(craft()->entryRevisions->getVersionsByEntryId($entry->id, $entry->locale));
        }

        // $localeFirstSave = ??
        // if ($entry->locale != $localeFirstSave)

        if (isset($versionsCount) && $versionsCount == 1)
        {
            $entry->slug = '';
        }
    });
}

another variant you could try is to always load the JS that generates the slug on the fly:

public function init()
{
    if (craft()->request->isCpRequest())
    {
        craft()->templates->includeJs('window.slugGenerator = new Craft.SlugGenerator("#title", "#slug");');
    }
}


Custom module that can define and have settings referenced (Craft 3) I'm currently working on migrating a Craft 2 project which has a bunch of bespoke custom plugins that provided various bits of additional functionality that's tailored to this project only. I've been reading up on the recommended approach in Craft 3 and have understood that modules are better suited in a lot of cases.

However, I've come across a snag with a previous Craft 2 plugin, that basically existed to provide settings that could be referenced in PHP/Twig. This plugin implemented various settings that were defined at config/mycustompluginhandle.php.

I'd like to have the same again but as a module, but it looks like the settings model isn't the same as a plugin and you have to "roll your own" setup for this.

My question is can is a module provide settings via a config/something.php file and can these settings be referenced in other parts of the application i.e. PHP/Twig or another plugin/module? If so, how can I go about doing achieving it?

So based on a bit of research. I don't think you necessarily have to create a settings model, if the settings are purely required from a config file. You could use something like:

$settings = Craft::$app->config->getConfigFromFile('configfilename');
$exampleSettings = $settings['exampleSomething'];

$settings would be an array, which you could then access each array key.


SCORM Player in Craft Has anyone ever tried and/or succeeded at integrating a SCORM player with Craft?

I'd like to "roll my own" LMS in Craft because Moodle is WAY overkill, but I need to be able to deliver SCORM content, as well as access and utilize the data provided by the SCORM files.

Not sure about specific integrations with Craft per se, but one way to achieve this fairly quickly is to integrate with SCORM Cloud's API. It is a SaaS offering that can be leveraged to add SCORM capability to just about any site, LMS, CMS, etc. Integrations with Moodle, WordPress, etc. already exist. See https://scorm.com/scorm-solved/scorm-cloud-features/


Set user based on their attachment to a product With Craft Commerce, I have a custom field that allows you to select which user from a defined group the product belongs to/is associated with.

I want to be able to set the user in order to access additional information about this user (profile info etc) and display this on the relevant product page.

How would I achieve this?

{% set user = product.usersFieldHandle.first() %} will give you the UserModel of the first related user.

Then e.g. {{ user.fieldHandle }}


Why is htaccess file not named ".htaccess" on fresh install? I run into the same error on each project setup with CraftCMS. So did I this time… again…

First of all: Yes, I seem to be a slow learner. And therefore I can't memorize to rename the htaccess file before calling the Craft installer page. ;)

When downloading CraftCMS the .htaccess file is called htaccess (without leading dot).
So, whenever I setup my Craft projects I have to rename the file that is located in /public.

But I always forget about that. I always run into the problem that I get a "503 Service Unavailable" on requesting my new website using Craft. On requesting the admin panel (to start the installer) I get a "404 Not Found". Then I only wonder and ask myself if I have made something terribly wrong…

Only after some hard thinking about what's going on there I come accross the solution:
Rename htaccess to .htaccess. Apache is not recognizing the one without dot.

This is happening always (and by "always" I mean each and every single time I start working on a new Craft project) to me and it's totally bothering me.

Why can't Craft jsut come with a correctly named .htaccess file?

Is the public htaccess file maybe named without the leading dot to not be hidden on operating systems like MacOSX? So you can copy files from folder to folder without missing hidden ones?
I mean, Craft is made for developers. Come on, guys. Developers should know to have in mind hidden files when copying them to a new project's destination.

So, why just not delivering Craft with .htaccess in /public folder instead of htaccess?

I guarantee you guys that I will forget about the renaming again before calling the URL of my next Craft project.

Because files that start with a . are considered "hidden" by many file systems (specifically OSX default).

If the file is hidden, then there's a good chance that the user won't know about it, and won't be able to FTP it to the server. It's better for the file to be intentionally misnamed, rather than accidentally hidden.


Error when trying to generate a PDF in Craft Commerce I am getting an error when trying to generate a PDF in Craft Commerce.

The error is:

  Undefined index: (/srv/data/web/vhosts/www.nihonshu-sake.lu/craft/plugins/commerce/vendor/dompdf/dompdf/lib/Cpdf.php:3855)
  $font = $this->fonts[$this->currentFont];

Craft Commerce 1.x uses the Dompdf package to generate PDFs.

The issue is likely a font cache issue, Dompdf caches an index about all fonts. Removing the cache indexes should fix the issue. Remove:

craft/plugins/commerce/vendor/dompdf/dompdf/lib/fonts/dompdf_font_family_cache.php

This is as mentioned in the migration guide and occurs because Craft Commerce has gone from Dompdf 0.6 to 0.8:

https://github.com/dompdf/dompdf/wiki/Migration-Guide

  The class naming conventions required a change to the dompdf_font_family_cache.php file. Though we have attempted to accommodate this change your first step when encountering bugs (if you don't know where to start) might be to reset your font directory (i.e. remove custom font files and the related font metrics files, and remove the non-dist, generated, font family cache file).

First try removing the dompdf_font_family_cache.php as mentioned above. If that doesn't work try removing all files they list above from the same folder. I think that includes all .afm. The directory should end up looking something like the original: https://github.com/dompdf/dompdf/tree/master/lib/fonts


How can I output child urls that reflect a structured menu hierarchy when the structure has no URL format specified? I am using a structure for navigation. The structure has two fields :
entry field: 'contentLink'
custom link: 'customLink'

These are used to create a menu structure like:
About
- sub item 1
- sub item 2
- sub item 3

The section for this is set to have no url templates setup.

The entry links for sub item 1 to 3 point at entries in a page structure called 'pages' which is currently flat (ie no children)

In my template i am using a drop-down menu and code to get child items which works OK.
    {% set menuentries = craft.entries.section('topnav') %}

{% for entry in menuentries %}

    {% if entry.contentLink.first|length %}
        {# attempt to set navlink var #}
        {% set navlink = entry.contentLink.first().slug %}

    {% elseif entry.customLink|length %}

        {% set navlink = entry.customLink %}

    {% endif %}

     {% if entry.level == 1 and entry.children|length %}

            {{ entry.title }}

                {% for child in entry.getDescendants() %}

                        {{ child.title }}

            {% endfor %}

    {% elseif entry.level == 1 and not entry.hasDescendants() %}

{{ entry.title }}

    {% endif %}
{% endfor %}

But i cant figure out how to get:
a) a url for child.slug that reflects the heirarchy of the menu structure
b) parent and child active classes for highlighting / breadcrumb purposes

question restated:
How can I output child urls that reflect the a structured menu hierarchy like: 'about/sub item1' when the structure has no URL format specified?

Craft can't really produce the uri patterns/routes you need automatically without giving it something to work with. With that said there are a couple of ways to approach this.

1) One option is to simply make your pages section into a structure; creating the needed hierarchy elements, and use it directly to generate your navigation. You may also want to specify additional 'entryType(s)' for header items, etc (i.e. items that don't have a corresponding page and/or are used exclusively for creating the nested route structure or for navigation headers, buttons, etc). You can then test entry.type in your template and deny or reroute the request accordingly.

2) Another option is to define a url format for your nav structure, which represents the uri pattern(s) that you would like to have (i.e. if the structure represents the site root then set the uri to {slug} and children to {parent.uri}/{slug}).

Using this approach, you would want to set up a template for your navigation structure which essentially includes the corresponding page template, as needed.

Something like this perhaps:

{% if entry is defined %}
    {% set relatedPage = entry.contentLink.first %}
    {% type = relatedPage.type %}
    {% include ["pages/_types/" ~ type, "pages/_types/default"] with { 'entry': relatedPage } %}
{% else %}
    {% redirect '404' %}
{% endif %}

Notice that when including the page template, we are redefining the entry variable to be the related page, so that the 'page' template doesn't have to worry about it, and can be loaded directly or via the navigation template as needed.

Note: you may want to disable urls for your pages channel if you don't ever want users to access pages through those routes.


Generate transforms only working on default install (multi-site) I have a multi-site setup running within Craft 3. Everything seems to be working nicely, except for image transforms. For example:
The following transform on the default site works correctly:
https://www.default-site.com/index.php?p=actions/assets/generate-transform&transformId=10406

The second-site transform gives an internal server error 500
https://www.second-site.com/index.php?p=actions/assets/generate-transform&transformId=10406

My 'second-site' index.php has the following constants:
define('CRAFT_SITE', 'second-site');
define('CRAFT_BASE_PATH', '/home1/client-dir');
define('CRAFT_STORAGE_PATH', CRAFT_BASE_PATH.'/storage');
define('CRAFT_VENDOR_PATH', CRAFT_BASE_PATH.'/vendor');
define('CRAFT_TEMPLATES_PATH', CRAFT_BASE_PATH.'/templates');

I should note that I'm using Amazon S3 to serve my assets (using the S3 plugin). Also, the assets field is set to relate assets from the default site.
UPDATE: In my log file, I'm seeing the following error:
2020-10-01 20:25:27 [-][-][-][error][Error] Error: Call to a member function getVolume() on null in /home1/client-dir/vendor/craftcms/cms/src/services/AssetTransforms.php:648
Stack trace:
#0 /home1/client-dir/vendor/craftcms/cms/src/services/AssetTransforms.php(603): craft\services\AssetTransforms->_generateTransform(Object(craft\models\AssetTransformIndex))
#1 /home1/client-dir/vendor/craftcms/cms/src/controllers/AssetsController.php(1179): craft\services\AssetTransforms->ensureTransformUrlByIndexModel(Object(craft\models\AssetTransformIndex))
#2 [internal function]: craft\controllers\AssetsController->actionGenerateTransform(11357)
#3 /home1/client-dir/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array(Array, Array)
#4 /home1/client-dir/vendor/yiisoft/yii2/base/Controller.php(157): yii\base\InlineAction->runWithParams(Array)
#5 /home1/client-dir/vendor/craftcms/cms/src/web/Controller.php(178): yii\base\Controller->runAction('generate-transf...', Array)
#6 /home1/client-dir/vendor/yiisoft/yii2/base/Module.php(528): craft\web\Controller->runAction('generate-transf...', Array)
#7 /home1/client-dir/vendor/craftcms/cms/src/web/Application.php(291): yii\base\Module->runAction('assets/generate...', Array)
#8 /home1/client-dir/vendor/craftcms/cms/src/web/Application.php(559): craft\web\Application->runAction('assets/generate...', Array)
#9 /home1/client-dir/vendor/craftcms/cms/src/web/Application.php(270): craft\web\Application->_processActionRequest(Object(craft\web\Request))
#10 /home1/client-dir/vendor/yiisoft/yii2/base/Application.php(386): craft\web\Application->handleRequest(Object(craft\web\Request))
#11 /home1/client-dir/public_html/second-site/index.php(28): yii\base\Application->run()
#12 {main}
2020-10-01 20:25:26 [-][-][-][info][application] $_GET = [
    'p' => 'actions/assets/generate-transform'
    'transformId' => '11357'
]

Craft Version: 3.4.24  Amazon S3 Plugin: 1.2.8
Has anyone else experienced this? Any ideas?

From Brandon Kelly on Discord:

If you go to the Assets index page and change the site to your second
site. Are you able to see all the same assets there? (Specifically
whatever ones appear to be causing this error on your second site)

They weren't listed.

Had a feeling that would be the case. That's your problem. If you run
php craft resave/assets, does that fix it?

Yes it did! Thanks :-)


Re-populate additional fields on Contact Form on failure of form validation I'm using additional fields on my contact form. I want to re-populate the additional fields if/when the form fails validation, but it's not working so far.

To re-populate a standard field, the code uses an attribute of message using dot syntax…

<input name="fromName" id="fromName" value="{% if message is defined %}{{ message.fromName }}{% endif %}" type="text">

But for additional fields the value is stored as an attribute of message.message using the subscript syntax (the use of square brackets below)…

<input name="message[Phone]" id="phone" type="text" value="">

I'm having trouble accessing the substring value on message.message. In my specific example, I have several radio buttons that need their selections remembered in case anything goes wrong. Here's what I expected to work…

{% for course in courses %}
    <input id={{ course.slug }}" name="message[Course]" type="radio" value="{{ course }}"
         {% if message is defined and message.message[Course] == course %}
             checked="checked"
         {% endif%}>
{% endfor %}

However, this code outputs the template error:

Variable "Course" does not exist.

How can I re-populate the additional fields for the contact form plugin?

From the changelog:

  1.7.0

  Added the ability to access individual message fields values via message.messageFields when a validation error occurred. For example, the value of the input message[Phone] can now be accessed via message.messageFields['Phone'].

So I think you should be using message.messageFields[Course] rather than message.message[Course]


Templating - Get a string of the entry's field handle I'm passing entry fields into a macro and I'd like to be able to get a string of the field handle

myMacro(entry.field1)
myMacro(entry.field2)

{% macro myMacro(entry) %}
  {# I want a string of 'field1' here #}
{% endmacro %}

You won't be able to do it that way because entry.field2 will return you the normalized field value and there is no way to trace back some object|string|variable to an unknown entry with an unknown field handle. You need to pass the handle as a second parameter in your macro

{% macro myMacro(field, fieldHandle) %}
    {{ fieldHandle }}
{% endmacro %}

myMacro(entry.field2, 'field2').

You could also pass the entry and a field handle instead of the field

{% macro myMacro(element, fieldHandle) %}
    {{ fieldHandle }}
    {% set value = element.getFieldValue(fieldHandle) %}
{% endmacro %}

myMacro(entry, 'field2').


Element Actions for Entries being viewed from modifyEntrySources Im using the modifyEntrySources hook in my plugin, when I view the entries based on my custom criteria it doesn't show the checkboxes for element actions, is there a way to get these back or is this a bug?

The checkboxes will only show up if there is at least one available element action for the current source.

Element actions are defined by element types’ getAvailableActions() methods, which will vary their response based on the $source that is passed in.

In EntryElementType’s case, if an unrecognized $source is passed in, then no actions will be returned.

However, EntryElementType::getAvailableActions() does have a hook called addEntryActions, which gives plugins the opportunity to add additional actions to its response.

So on top of using the modifyEntrySources hook, you can also use the addEntryActions hook to provide the actions that your custom source should have.

public function addEntryActions($source)
{
    if ($source == 'myCustomSourceKey')
    {
        $elementType = craft()->elements->getElementType(ElementType::Entry);
        return $elementType->getAvailableActions('section:X');
    }
}

(Replace X with the ID of a section you want to mimic.)


Moved from dev to prod server, admin page blank I have a dev server (sandbox.site.com) and a prod server (www.site.com). I copied over the contents from sandbox to dev using cp -r. Loading up my website on the production site looks fine. Everything is where it should be, the few entries I have in place loaded, images are there, etc.

The problem comes when trying to load the admin panel; I get a white screen. I enabled devMode and that gave me the login fields with no styling. I am unable to login (99% certain I have the user/pw right) and there are no error messages.

I searched for "error" in my craft.log, but nothing really stood out at me. I have a lot of the following errors:

[exception.Craft\HttpException.404] exception 'Craft\HttpException' in /home/user/craft/app/controllers/TemplatesController.php:59

but the timestamp isn't the same time as trying to login to the control panel.

Any thoughts?

I found the problem - the htaccess file was still the old EE file that had been there. Once I uploaded the Craft-provided htaccess file, I was able to get back into the control panel. Thanks for the help guys!


Configuring Apple News I installed the plugin for Apple News (https://github.com/pixelandtonic/AppleNews) but did not understand the configuration instructions.

I created a file at craft/config/applenews.php with the following:

<?php

return [
'channels' => [
    [
        'class'     => 'applenewschannels.MyNewsChannel',
        'channelId' => 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
        'apiKeyId'  => 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
        'apiSecret' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    ],
  ],
];

I created a craft/applenewschannels folder and added MyNewsChannel.php and MyNewsArticle.php but the “Apple News Channels” pane has not appeared on the edit entry page. What am I missing?

I had this issue and solved it by ensuring that the locale checked against in the matchEntry() function in MyNewsChannel.php matched the locale of my site.

The example channel class provided in the plugin repo checks for a site locale set to en on line 27:

if ($entry->locale != 'en') {
return false;
}

My site locale was set to en_us; correcting it in my channel class solved this for me. Maybe this is also the case for you or someone else who has landed here with a similar issue!


Customize elementSelect Field's Modal Table Layout I am using the "Select Entry" field (_includes/forms/elementSelect.html) field in a custom plugin to select one of my custom element types.

In my ElementType, I defined defineTableAttributes() and getTableAttributeHtml() to customize the table cells on a index view of the Element.

Now when I am using this Element in a modal view, it displays the same cells as on the index view, but I would like to hide certain fields (like buttons).

Is there a way to customize the returned fields, without building the whole modal myself, like mentioned here?

I saw, that a attribute context gets passed, which is either modal or index, but I don't know how I could access it.

Thanks!

You should be able to accomplish what you want with a combination of the getTableAttributeHtml() hook and the modifyEntryTableAttributes() hook. You may be able to use the parameter $source from modifyEntryTableAttributes() to filter out index vs modal.

Check out this post for a more detailed description.


Save and show card fee for Commerce plugin How do I save and show the credit card fee on the order page. When I get the response from the gateway I too get the credit card fee amount but it's not being added to the order and isn't viewable anywhere - does anyone have any experience with that?

I would save the response to an incognito field (or fields) on your order (probably both the entire response and also just the fee separate out).

https://github.com/mmikkel/IncognitoField-Craft

The readonly incognito field is particularly good for this sort of thing - I use a bunch of these fields in a debug tab on my order layout to save useful things.

Just create the fields, add the fields to your order, and you update the values with the usual <input name="fields[fieldName]"> syntax with any cart operation, or use setContentFromPost if you're in a plugin:

    $order->setContentFromPost(array(
        'fieldName' => $creditCardFee,
    ));
    craft()->commerce_orders->saveOrder($order);


Array from matrix fields without quotations I am trying to create an array bodyBlocks by looping through all of my matrix fields called blockTextContent:

$bodyBlocks = [];
foreach ($entry->getFieldValue('pageBuilder')->all() as $block){
    switch ($block->type->handle) {
        case 'blockText':
            $bodyBlocks[] = $block->blockTextContent;
            break;
        }
    }

// Begin defining the response data for this entry
$data = [
    'title' => $entry->title,
    'slug' => $entry->url,
    'status' => $entry->status,
    'textArea' => $bodyBlocks
];

The JSON response is as below, focusing on the textArea line.

"title": "Title Here",
"slug": "slug-here",
"status": "live",
"textArea": [
    "
Text from first 1st block
",
    "
Text from first 2nd block
",
    "
Text from first 3rd block
",
],
"heroBanner": "img.jpg",

The above is working as expected, cool. BUT I'd like the response to appear as below. Merging that matrix field in to one line in textArea, so without the separating quotation marks and surrounding square brackets [ ]?

My desired response would look like this in the end:

"title": "Title Here",
"slug": "slug-here",
"status": "live",
"textArea": "
Text from first 1st block

Text from first 2nd block

Text from first 3rd block
",
"heroBanner": "img.jpg",

Thanks!

You would need to join the array into a string, like so:

// Begin defining the response data for this entry
$data = [
    'title' => $entry->title,
    'slug' => $entry->url,
    'status' => $entry->status,
    'textArea' => implode(' ',$bodyBlocks)
];


Outputting image assets with flickity I'm trying to use flickity to create a draggable gallery on a single entry template, but I'm having issues with the output.

In the backend it looks like this. A field using multiple assets.

Without flickity I'd put them out like this which lists each image from the field.

{% if entry.gallery|length %}
    {% for image in entry.gallery.all() %}

    {% endfor %}
  {% endif %}

For flickity to work it needs to look like this

I have trouble combining these two things successfully. The goal is to dynamically output each image from the assets into a carousel-cell div. Does anyone have pointers how to do so? Thank you!

If I understand the question properly, this should do it for you:

{% if entry.gallery|length %}

    {% for image in entry.gallery.all() %}

    {% endfor %}

{% endif %}


Displaying an array returned from a hook I'm writing a plugin which has a hook like:

craft()->templates->hook('myHook', function(&$context)
{
    return array('hello', 'there');
});

While I can call it in a template with:

{% hook myHook %}

I get an "Array to string conversion", understandably. But I can't work out how to treat the returned data like an array. How can I use hook 'myHook' in a for loop, or set it to a variable? It must be simple, but I've exhausted my random attempts.

Template hooks are useful if you need to change the current twig context array somewhere inside of a template. If you make any changes to $context inside of your hook's function, those changes will be available after your hook tag.

If you just need to return some text or an array, a variable will do the trick just fine!


How to get current site (locale) api / plugin For my form plugin I'm using a global set of fields. These can be set in 2 languages default and en.

Problem is whenever I try to output them I cant dynamically make them use the current site locale/multi-site.

This is the current code:

$localeHandle = Craft::$app->getSites()->getCurrentSite()->handle;
    // form texts
    $entries = GlobalSet::find()
        ->siteId('*')
        ->site($localeHandle)
        ->handle('popupContact')
        ->asArray()
        ->one();

If $localeHandle is set to either default or en it works. I cant figure out how to get the handle though. Documentation doesn't state anything either.

Edit:
Craft::$app->getSites()->getCurrentSite()->handle; returns the default site handle.

I don't know if this was the problem you were having but I was not including the site's first URL segment like /en/ (in your example) with the controller action URL. So you'd want to post to /en/actions/pluginHandle/controllerClass/actionMethod to get the English site back when using Craft::$app->getSites()->getCurrentSite() in your plugin.

I posted a more thorough answer to the same problem in another ticket:
https://craftcms.stackexchange.com/a/33941/4433


Craft is unable to determine if an update is available at this time No chance to update on my local machine and on my live site.
On the staging site it works but that's the same server as the live site.

I've cleared the caches and checked the logs.

Local there is only this error:

2016/06/19 19:41:01 [error] [application] Error in Craft\Et::phoneHome. Message: Cannot overwrite an existing license.key file.

But I run the site in DEV Mode.

Any ideas? I'm a bit unhappy about it :/

Best
David

You're getting that error message because there is an existing craft/config/license.key file in place for your local installation and there is no record of that install on the Craft/web service end.  Likely you've just copied an existing license.key file from another site into this new installation.

So the web service on the Craft end thinks that since it's a new Craft client installation it needs to send down a new license.key file for you to start using.  But the Craft client knows it should never overwrite an existing license.key file, so it reports that error.

Solution: remove the existing license.key file (since it probably belongs to another site anyway) and let the web service generate a new one for you.


Auto-login on account activation Anybody got any suggestions on debugging autoLoginAfterAccountActivation and activateAccountSuccessPath not working?

These are set in general.php of my config but when a user activates their account (sets their password) they are redirected to the homepage and not logged in. The user is showing as active in the control panel.

Hayelp!

Hayelp! http://www.cartoonscrapbook.com/01pics-L/penelope-pitstop_L20.jpg

(Not necessarily a great answer to your question, but it's in the same wheelhouse and might be handy if you're working in this area)!

I remember having issues with this myself (to be honest the precise details are a bit lost in time for me - but basically IIRC it's by design that they're not logged in after creation, perhaps to force them to practise login/their password?  I can't remember but do remember I found it odd behavour) - anyway in my case the issues arose as part of adding user registration during commerce checkout.  It was discussed on Slack and the solution was that Steve Rowling made a very handy plugin to auto-login newly created users:
https://github.com/steverowling/autologin

I'm using it, works a treat.

(I should also wrap up my code for registration during checkout as a plugin and release that one of these days!)


Moving to another database: "Specified key was too long" I am attempting to move the database from my local machine running MySQL 5.5.38 to my webhost running 5.1.70. However when I do so I get the following error on at least two tables. I am using a MySQL export/import process.

  #1071 - Specified key was too long; max key length is 1000 bytes

Does anyone have any idea how I might overcome this problem, or what is causing it?

I bumped into this last week, and it is exactly as you suspect... your new database does not support InnoDB, which is a requirement of Craft.

I'd suggest discussing the matter with your hosting company. In my case, the hosting company was unable to offer InnoDB support in any form, therefore disqualifying them as a viable hosting option for our new site.


Search/return entries with custom field length less than 200 So I'm not sure this is possible with the entries search param but I'm trying to return entries where a field (rich text) has fewer than 200 characters. This is obviously horribly wrong but something like...

{% set params = {
    limit: 3, order: 'RAND()', search: 'quote:|length < 200', section: 'quotes'
} %}

Any help much appreciated!

I'm not 100% sure what you are trying to achieve but If its because all the others would be to big for whatever you're building. You could use Hacksaw to fit all your text.

https://github.com/ryanshrum/hacksaw


A user deleted my craft Admin account, what to do? A created user was able to delete the Admin account, now I can't log in Craft anymore with an admin account. How is it possible that a normal user can delete an Admin?
I'm in contact with this user to try and re-activate the Admin account because I think the Soft delete is at work here, so fingers crossed!

You need to check if the normal user has an administrate permission, you can check at user -> permission. Even a normal user you still can give it an administrate user permission without change it into a admin user, but this permission is off by default for normal user.


Date specific conditional Hi I'm trying to template out a simple conditional that shows content if the date set in a date field is greater or equal to today, and I can't seem to get the syntax quite right.

I have tried this:

{% if entry.promoEndDate|date ('>= ' ~ now) %}

Price valid until {{ entry.promoEndDate | date('d M Y') }}

{% endif %}

And this:

{% if entry.promoEndDate | date >= now | date %}

Price valid until {{ entry.promoEndDate | date('d M Y') }}

{% endif %}

Both don't yield the result I'm looking for.
Probably missing something really simple here but looked at it too long now.

Thanks in advance

You should be able to just compare the two dates directly.

{% if entry.promoEndDate >= now %}

Price valid until {{ entry.promoEndDate|date('d M Y') }}

{% endif %}


What's the difference between using single and double quotes in strings? Is there a difference between using single-quoted and double-quoted strings?

There is a small difference, single-quoted strings don't support interpolation:

{% set string = 'There is a #{car}.' %}

The above example won't work. If you want to use it, you need to wrap your string in double quotes:

{% set string = "There is a #{car}." %}


How do you debug problems with a migration? I've created a simple migration to create a table for my plugin, but when I update the plugin via the CP, I get the following message:

  Craft was unable to install this update :(

  The site has been restored
  to the state it was in before the attempted update.

  There was a problem updating your database.

As it's the only change to the plugin I think it's safe to say my migration isn't up to task.

How do I know exactly what's wrong with my migration though? There don't appear to be any logs generated to show the actual error being caused. I'm running in devMode, and I can't see anything in the browser console and there don't appear to be any errors in the standard logs.

For reference, here is the migration I'm trying to run, which was created manually rather than using yiic:

<?php
namespace Craft;

/**
 * The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_migrationName
 */
class m171129_103222_myplugin_createLogTable extends BaseMigration
{
    /**
     * Any migration code in here is wrapped inside of a transaction.
     *
     * @return bool
     */
    public function safeUp()
    {
        craft()->db->createCommand()->createTable('myplugin_log',
            array(
                'eventId' => array(AttributeType::Number, 'required' => true),
                'level' => array('column' => ColumnType::Varchar, 'maxLength' => 5, 'required' => true),
                'message' => array(AttributeType::String, 'required' => true),
                'date' => array(AttributeType::DateTime, 'required' => true),
            ));

        return true;
    }
}

Logs should be written to craft/storage/runtime/logs to help debug issues like this.  It gets a little sketchy with fatal errors, though.  Logs get flushed to disk when the onEndRequest event gets successfully fired.  If it's a fatal error that kills script execution, that event will never get fired and the logs don't get flushed.  That might have been what you're running into here.

Outside of that, to answer your original question, the absolute best way to debug stuff like this is with xDebug.  PhpStorm has a native xDebug client built in and it's pretty fantastic.


How do I pull related entries and assets? I'm having a bit of a hard time wrapping my head around exactly how to work with both Relationships and Assets. Here is my current problem that I seem to be stumped on, i'm sure once I get this going I'll be good to go and fully understand how to work with both:

I need to determine if an entry is selected to be related to an entry single (the homepage) via the entry field 'featuredEvent', then
I need to determine if the 'image' block is being used in the matrix 'articleBody' in that related entry, then
I need to pull the first instance of the 'image' block (not necessarily the first block altogether), then
I need to determine if there is more than one 'asset/image' in the 'image' field in the 'image' block in the related entry, then
If there is only one image I need to output some code, and then output the image, as well as the other parameters 'size' & 'alignment', which are both drop downs, 'size' selects the pre-determined 'imageTransform' where as 'alignment' just applies a class or
If there are multiple images i need to output some code, and then output the images, as well as the other parameters 'size' & 'alignment'.

Could anybody write that code out for me and explain what is happening in each line to help me get a better grasp? Thank you so much in advance.

The data in Craft is handled mostly by Models (and arrays of Models). Before pulling actual information, you define your criteria in an ElementCriteriaModel using generic parameters and parameters specific to what you are trying to get (entries, assets, etc.). You then use one of the ElementCriteriaModel's functions to pull the actual data. You will get either a model or an array of models to loop over. This works the same for most things in Craft because most things are Elements.

You can look under the Variables heading in the side menu of the templating docs to see the kinds of models you will get.

On your homepage, you start with an automatically created entry model (this is created on every page that Craft recognizes as an entry's page). Here's the basic code you need:

{% for event in entry.featuredEvent %}
    {# Output some event code here #}
    {% set block = event.articleBody.type('image').first() %}
    {% for image in block.image.find() %}
        {# Output some image code here #}
        <img src="{{ image.getUrl(image.size) }}" class="{{ image.alignment }}">
    {% endfor %}
{% endfor %}

So an explanation of the above. In Craft, related elements are not automatically pulled from the DB. Instead each field that points to a related element (entries, assets, categories, users, etc.) is an ElementCriteriaModel so that you add more criteria before pulling. So entry.featuredEvent is an ElementCriteriaModel that points to all of your featured event entries.

When working with ElementCriteriaModel you have a few options to pull the data and use it. In the above code, when you give a for loop ElementCriteriaModel it will automatically pull the data and give the loop entries. So we take the entry.featuredEvent, and loop over the entries that's given to us when we use it in the for loop.

Inside the for loop, we pull the first image block in event.articleBody. Because matrix blocks are elements, we get the same features. So we set the type, and pull the first one.

In the next for loop, we are grabbing all of our images in the image block. The tricky part here is that we can make the code a little more efficient by simply pulling all of the images and looping over them. If you have very different html you plan on using for one image and multiple images, you will need to set the images as a variable like we did the block. You can then check the number of images using the length filter, and either Craft's switch tag, or a couple if statements.

Personally, I recommend using the loop, and using CSS to make the style differences you need.

Finally, we output each image. Because you're using a transform on them, we can't use each assets getImg function. Instead we write the img tag manually and grab the transformed url using getUrl.

The next bit is making a couple assumptions. I'm assuming that size is a image transform handle. I'm also assuming that these fields are on the asset. If they're on the matrix block, replace image.size and image.alignment with block.size and block.alignment.


How do I render specific child entries of a structure based on url segment For simplicity, I'm building a site for a restaurant. The "Menu" page has the following url(s):

mysite.com/food/appetizers
mysite.com/food/sandwiches

food is a structure. It contains every entree the restaurant has. I've nested the actual entree to under the corresponding category. For example:

mysite.com/food/appetizers
                         /cheese-curds
                         /french-fries

mysite.com/food/sandwiches
                        /whole-sandwich
                        /half-sandwich

..and so on.

On mysite.com/food/ I can render all entrees under thier corresponding category like this:

{% set entries = craft.entries.section('food') %}

 {% for entry in entries %}
       {% if entry.type == 'category' %}

{{ entry.title }}

       {% endif %}

       {% set children = entry.getChildren() %}
       {% for child in children %}

{{ child.title }}

       {% endfor %}
 {% endfor %}

Everything is working great. All entrees are listed below their corresponding "category" on my /food/ page. I can click on each individual entree "cheese-curds" for example, and can get the entry details.

For templates I have _entry and index.

index is used on mysite.com/food _entry is used on each entree.

Where I'm stuck is how to render the entries for the current category. For example:

mysite.com/food/appetizers

I'm not sure How to get past my initial command of getting ALL entires:

 {% set entries = craft.entries.section('food') %}

 {% for entry in entries %}
       {% if entry.type == 'category' %}
       ....
       ....

To only this:

{% if entry.type == 'category' %}
  ....
  ....

So that I am only listing out the entries for the current category. It's OK if I need to create a new template, I'm not sure how to tell Craft how to do that. Or is there a better approach to getting all entries for the structure? It seems simple enough in theory, I keep talking myself in circles.

EDIT

Thank you @j00lz
Your solution makes perfect sense. I think I either don't quite understand, or I'm still at the same spot I was before.

{% switch entry.level %}
    {% case 1 %}
        {# this is mysite.com/food #}
        {# outputs #}
        Appetizers
            Cheese Curds
            French Fries
        Sandwiches
            Sandwich One
            Sandwich Two
    {% case 2 %}
        {# this is mysite.com/food/appetizers
        {# outputs #}
        Appetizers
            Cheese Curds
            French Fries
    {% case 3 %}
        {# this is mysite.com/food/appetizers/french-fries
        {# outputs #}
            French Fries
            French fries are awesome!
{% endswitch %}

So, it's like I need another template to only show the 2nd case on the page.
I can list all foods, and the actual entrée (3rd case) using 2 templates. I'm hung up on that middle page where it would only list the title of the entrée, and then the children entrée.

I thought about putting an if statement at the top of the page that checks the URL level. If it's only /food/ do "x", if its /food/appetizers do "y", but that seems to assume an awful lot.

Maybe there is a better route to go all together. I only had a structure in mind because of the nested elements that I wanted to be able to control where they were.

Probably the simplest way is to split the code up like this in your template.

{% switch entry.level %}
    {% case 1 %}
        {# all the food #}
    {% case 2 %}
        {# course level #}
    {% case 3 %}
        {# one dish #}
{% endswitch %}

This give you a lot of fine control over each level of your structure.

Or even simpler:

{% set entries = craft.entries.section('food').descendantOf( entry ) %}

and run the same loop regardless of which level you are on.

You can also have a look at this page to see how to create a navigation for a structured section.

And if you want elaborately styled menus check out this link


How do I create a well formed CSV or XML to succesfully import entries with assets and categories? The source website is in ExpressionEngine and I know how to get data out, but I don't know how to structure it and succesfully import entries into Craft where assets and categories also imported. I have tried the plugin FeedMe (XML) and I also tried the plugin Import (SVG).

How to work with categories and sub categories an how to use multiple assets with import? Thanks in advance!

<?xml version="1.0" encoding="UTF-8"?>
    <products>
        <entry>
            <title>My product title</title>
            <slug>my-product-title</slug>
            <![CDATA[
My body text
]]>
            <assets>
                <![CDATA[
                    http://www.mywebsite.nl/root/path/image1.png,
                    http://www.mywebsite.nl/root/path/image2.png
                ]]>
            </assets>
            <category>
                <![CDATA[
                   Lightning,
                   Cities,
                   Standard,
                   Special
                ]]>
            </category>
        </entry>
    </products>

I used FeedMe successfully and this is what I used. The images have to be already present as assets in Craft(ftp and then update asset indexes). Having the full url in the images part stumped me too. In this example I pulled the images twice because in my EE build I was using the first image of many to create a preview image and in craft I actually created a preview image field.

<entry>
    <entry_date>{entry_date format="{DATE_ATOM}"}</entry_date>
    <title>{title}</title>
    <slug>{url_title}</slug>
    <price>{product_price}</price>
    <dimensions>{product_dimensions}</dimensions>
    <description>{product_description}</description>
    <notes>{private_notes}</notes>
    <location>{product_location:title}</location>
    <number>{product_number}</number>
    <message><![CDATA[{product_message}{option}, {/product_message}]]></message>
    <status>{status}</status>
    <category><![CDATA[{categories}{category_name}, {/categories}]]></category>

    <images><![CDATA[
    {finalproductimages}
        {filename}.{extension},
    {/finalproductimages}]]></images>

    <preview><![CDATA[
    {finalproductimages limit="1"}
        {filename}.{extension},
    {/finalproductimages}]]></preview>

</entry>


Recoverable error Object of class Craft\ElementCriteriaModel could not be converted to string after Update After running Craft update I'm getting error on the meta author, meta description and meta keywords fields. Any idea how to resolve issue?

  Recoverable error
  Object of class Craft\ElementCriteriaModel could not be converted to string

Error Output:

Template Code:

{% set site_title = 'site title here' %}

{#
    ENTRY FALLBACK
    Not all pages have entries associated with them, e.g. search results, login page, etc.
#}
{% if entry.id is not defined %}
    {% set entry = craft.entries.id(2) %}
{% endif %}

{#
   HOMEPAGE DATA
   Used as a fallback for when meta values don't exist in this entry
#}
{% set homepage_entry = craft.entries.id(2) %}

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>{{ entry.id == '2' ? site_title : entry.title ~ ' > ' ~ site_title }}</title>
    <meta name="author" content="{{ entry.metaAuthor ? entry.metaAuthor : homepage_entry.metaAuthor }}" />
    <meta name="description" content="{{ entry.metaDescription ? entry.metaDescription : homepage_entry.metaDescription }}" />
    <meta name="keywords" content="{{ entry.metaKeywords ? entry.metaKeywords|join(',') : homepage_entry.metaKeywords|join(',') }}" />
    <link rel="shortcut icon" href="images/favicon.ico" />
    <link rel="stylesheet" type="text/css" href="/css/all.css">
    <link rel="stylesheet" type="text/css" href="/css/nav.css">
</head>

Any idea what issue is, how to resolve and why this broke?

Try something like this:

{% set author = entry.metaAuthor|length ? entry.metaAuthor[0] : homepage_entry.metaAuthor[0] }}

<meta name="author" content="{{ author }}" />


Can't assign a parent page to an entry I was changing some entry types to allow for a parent/child structure when I realised that this was already something Craft could do natively. When I undid my changes and attempted to assign a parent page, I am given the following error:

  Object of class Craft\Entry Model could not be converted to int.

I am still fairly new to Craft so I am quite limited in understanding exactly what I did to break it. I can still create and edit entries, I just can't set a parent page anymore.

******************************************************************************************************
2017/10/13 22:37:16 [warning] [application] There was a problem parsing the feed: cURL error 60: SSL certificate problem: unable to get local issuer certificate

******************************************************************************************************
2017/10/13 22:37:58 [error] [php] Object of class Craft\EntryModel could not be converted to int (C:\wamp64\www\craft\storage\runtime\compiled_templates\9a\9a68f00c27a5bff3f289231a8d85ef2d821f962bf46e9f246c88cce64dc926f2.php:19)
Stack trace:
#0 C:\wamp64\www\craft\app\etc\templating\BaseTemplate.php(26): __TwigTemplate_22da5c53ac1ef5202e2f12c05417214f2feda1f7c6b451fbb37fa9ade742e5bd->displayWithErrorHandling()
#1 C:\wamp64\www\craft\app\vendor\twig\twig\lib\Twig\Template.php(403): __TwigTemplate_22da5c53ac1ef5202e2f12c05417214f2feda1f7c6b451fbb37fa9ade742e5bd->displayWithErrorHandling()
#2 C:\wamp64\www\craft\app\vendor\twig\twig\lib\Twig\Template.php(411): __TwigTemplate_22da5c53ac1ef5202e2f12c05417214f2feda1f7c6b451fbb37fa9ade742e5bd->display()
#3 C:\wamp64\www\craft\app\services\TemplatesService.php(388): __TwigTemplate_22da5c53ac1ef5202e2f12c05417214f2feda1f7c6b451fbb37fa9ade742e5bd->render()
#4 C:\wamp64\www\craft\app\helpers\ElementHelper.php(122): Craft\TemplatesService->renderObjectTemplate()
#5 C:\wamp64\www\craft\app\services\ElementsService.php(1556): setUniqueUri()
#6 C:\wamp64\www\craft\app\services\EntriesService.php(176): Craft\ElementsService->saveElement()
#7 C:\wamp64\www\craft\app\controllers\EntriesController.php(462): Craft\EntriesService->saveEntry()
#8 C:\wamp64\www\craft\app\framework\web\actions\CInlineAction.php(49): Craft\EntriesController->actionSaveEntry()
#9 C:\wamp64\www\craft\app\framework\web\CController.php(308): CInlineAction->runWithParams()
#10 C:\wamp64\www\craft\app\framework\web\CController.php(286): Craft\EntriesController->runAction()
#11 C:\wamp64\www\craft\app\framework\web\CController.php(265): Craft\EntriesController->runActionWithFilters()
#12 C:\wamp64\www\craft\app\framework\web\CWebApplication.php(282): Craft\EntriesController->run()
#13 C:\wamp64\www\craft\app\etc\web\WebApp.php(823): Craft\WebApp->runController()
#14 C:\wamp64\www\craft\app\etc\web\WebApp.php(287): Craft\WebApp->_processActionRequest()
#15 C:\wamp64\www\craft\app\framework\base\CApplication.php(185): Craft\WebApp->processRequest()
#16 C:\wamp64\www\craft\app\index.php(62): Craft\WebApp->run()
#17 C:\wamp64\www\public_html\index.php(19): require_once()
REQUEST_URI=/public_html/admin/entries/pages/90-cherries

I was able to fix the issue - it had to do with the URL structure I had set in the Section's URL format area. For nested entries, I had put {parent-uri}/{slug} when in fact it needed to be {parent.uri}/{slug}.

I can now assign parents to entries and this is reflected in the URLs on the front end.


Recipients as dropdown with Contact Form Plugin I need to give users the ability to be able to choose which channel of the company their message goes to, i.e. General Inquiries, Estimates etc. using the P&T Contact Form Plugin and a select box. How would I be able to make that work?
Thanks!

A custom dropdown that allows you to trigger emails to different departments is possible using Sprout Forms and the Sprout Fields Email Select field.


Efficiently writing multiple transforms I use a responsive image plugin similar to picturefill.

On my local environement it works well, on my live install however the last trasnform isn't applied and I receive a 404. I guess it might be some memory_limit issue, so I wonder if there is a more efficent way to write this:

{% set fullw_trans_xs = { mode: 'crop', width: 767, } %}
{% set fullw_trans_sm = { mode: 'crop', width: 768, } %}
{% set fullw_trans_md = { mode: 'crop', width: 992, } %}
{% set fullw_trans_lg = { mode: 'crop', width: 1200, } %}
<img class="bttr img-responsive" alt="{{asset.title}}"
   data-bttrlazyloading-xs='{"src": "{{ asset.getUrl(fullw_trans_xs) }}", "width" : {{ asset.getWidth(fullw_trans_xs) }},  "height" : {{ asset.getHeight(fullw_trans_xs) }}}'
   data-bttrlazyloading-sm='{"src": "{{ asset.getUrl(fullw_trans_sm) }}", "width" : {{ asset.getWidth(fullw_trans_sm) }},  "height" : {{ asset.getHeight(fullw_trans_sm) }}}'
   data-bttrlazyloading-md='{"src": "{{ asset.getUrl(fullw_trans_md) }}", "width" : {{ asset.getWidth(fullw_trans_md) }},  "height" : {{ asset.getHeight(fullw_trans_md) }}}'
   data-bttrlazyloading-lg='{"src": "{{ asset.getUrl(fullw_trans_lg) }}", "width" : {{ asset.getWidth(fullw_trans_lg) }},  "height" : {{ asset.getHeight(fullw_trans_lg) }}}'
            />

I saw the answer of Brandon Kelly about retina images with that macro thing but frankly, I don't get it. Could that be applied in some way to solve this problem as well?

Okay, I found the issue.

It was the caching. I cleared the cache in the cp and emptied the craft_assettransformindex table

I deploied the site to my live server but had the image folder on svnIgnore, so craft tought the images would still be there and didn't try to recreate them.

This answer helps.


Plugin access and control panel navigation I have created a plugin.  It works fine for admins.  The plugin is in the CP nav and the admins urls work as expected, but when I login as a user who is not admin, the plugin will not display in the CP nav and the user cannot view the urls.  You get the error message:

 You don’t have the proper credentials to access this page.

What can I do to fix this?

You must give your users the “Access [Plugin Name]” permission.

You can either grant that permission directly to each individual user from Users → [User Name] → Permissions, or if each of the users belongs to the same user group, you can go to Settings → Users → [User Group Name] and grant the permission from there instead.