"PHP Warning: var_export does not handle circular references" when devMode = true When devMode is true, both the front end and admin of my site give me the PHP warning:

  "var_export does not handle circular references".

I've tried disabling plugins, with no luck.

The current solution i know of is to change CLogFilter's default dumper from:

public $dumper='var_export';

To:

public $dumper='print_r';

It even has a comment above it:

/**
 * @var callable or function which will be used to dump context information.
 * Defaults to `var_export`. If you're experiencing issues with circular references
 * problem change it to `print_r`. Any kind of callable (static methods, user defined
 * functions, lambdas, etc.) could also be used.
 * @since 1.1.14
 */

My previous answer was criticised because I obviously wasn't clear enough. As for the age of this question, it's only 2 months old.

Note: I've told P&T about this.


Edit a checkbox field within table field from the front end This is an extension of a question I posted here earlier, but another layer of complexity.

I'm trying to have a checkbox field within a table field be checked/unchecked from a front end form.

I've tried a number of scenarios using the example found here in the docs, but no dice.

Here is my current code:

      {% for row in currentUser.providerPayment %}

        Sliding scale?

        {% for slidingScale in currentUser.providerPayment  %}
            {% set checked = false %}

            {% if slidingScale.selected %}
                {% set checked = true %}
            {% endif %}

            {% if not checked %}
                <input type="hidden" name="fields[providerPayment][0][col2]" value="">
            {% endif %}

            <input type="checkbox" value="{{ slidingScale.value }}" name="fields[providerPayment][0][col2]" {% if checked %} checked="checked"{% endif %}>
        {% endfor %}
    {% endfor %}

And here is the error it's producing:

Update Here are my table field settings:

First, when you do this:

{% for row in currentUser.providerPayment %}

    ...

    {% for slidingScale in currentUser.providerPayment %}

you’re looping through the currentUser.providerPayment array (the rows in your providerPayment Table field on the current user) within another loop through the same array. If the table has 2 rows, this is what would be happening:

Row 1 (assigned to row)

Row 1 (assigned to slidingScale)
Row 2 (assigned to slidingScale)

Row 2 (assigned to row)

Row 1 (assigned to slidingScale)
Row 2 (assigned to slidingScale)

(Doesn’t make any sense.)

You only need a single for-loop here, and it’s the outer one. Within that loop, you will be able to access all of the values on the current row, via the row variable you’ve defined:

{% for row in currentUser.providerPayment %}

    {{ row.averageCostPerSession }}
    {{ row.slidingScale }}
    {{ row.acceptedPaymentMethods }}
    {{ row.acceptedInsuranceCarriers }}

{% endfor %}

Does that make sense?

So, for each row, if you want to output a checkbox input, you would just do this:

{% for row in currentUser.providerPayment %}

        <input type="checkbox" value="1"
            name="fields[providerPayment][0][col2]"
            {% if row.sliderScale %} checked="checked"{% endif %}>

{% endfor %}

One thing to keep in mind with checkboxes, though, is that they don’t actually submit any POST data if left unchecked. So to be safe, you should put a hidden input right before the checkbox input, with a blank value, which will act as the default value if the checkbox is left unchecked:

{% set name = 'fields[providerPayment][0][col2]' %}

{% for row in currentUser.providerPayment %}

        <input type="hidden" name="{{ name }}" value="">
        <input type="checkbox" name="{{ name }}" value="1"
            {% if row.sliderScale %} checked="checked"{% endif %}>

{% endfor %}


Matrix Issues After Upgrading from 2.4 to 2.6 Running into some issues with matrix fields after upgrading from 2.4 to 2.6.

The matrix in the site includes a whole bunch of block types that are used to build row-based pages (e.g., Intro, Profile, News, Text, etc.).

When creating a new page everything works just fine at first. However, when you insert certain block types into the matrix, suddenly you can no longer reorder/collapse/add blocks in that matrix.

I notice that when it breaks, the following error pops up in the console:

Uncaught: TypeError: Cannot read property '0' of undefined - velocity.min.js

Anyone run into this or have ideas to what this might be? I can't seem to find a commonality between the blocks that cause the error and am not sure where to go with this.

Note: this particular matrix config has a ton of fields (we've had to extend the php memory limit etc. when saving changes to the config).

Tks in advance!

Craft 2.5 changed from Redactor I to Redactor II, so chances are you just need to update your Redactor configs to the new format: https://craftcms.com/support/redactor-ii-configs


Cannot connect to outside mssql database in production Error: Craft CMS can’t connect to the database with the credentials in config/db.php.
I have two database connections. One to mysql for the bulk of the website including all things craft, and one connection to mssql. I modified /config/app.php to include the mssql connection credentials to access them via twig:
        {% set myquery = craft.query()
        .select(['*'])
        .from(fromSql)
        .orderBy('Project ASC')
        .all(craft.app.theMSSQLConn)
        %}

This works on my local and staging environment, but the errors start on production. The file throwing the errors (mysite/vendor/craftcms/cms/src/db/Connection.php) first threw an error "Craft CMS requires the PDO_PGSQL driver to operate". I'm not using pgsql, but I installed the extension anyways and now I have a new error, in the same function of open(), stating craft cannot connect to the database with the credentials in config/db.php. The file config/db.php contains the mysql credentials which are correct and are working. I'm not sure what to do. It seems like Craft is attempting to open my mssql connection using the credentials in config/db.php as opposed to the credentials provided in config/app.php.
Edit: craft.app.theMSSQLConn is returning the correct connection string.
For more context, I was following an article by Andrew Welch here: https://nystudio107.com/blog/cutting-the-cord-removing-plugins#plugin-4-connect

Answer:
The server I was trying to connect to didn't have a CNAME set up in my corporate dns. So when I would switch environments some environments could see the server and others could not.


Breadcrumbs for category pages I'm a Craft first-timer building a simple blog site. I want to include breadcrumbs at the top of each page like so:

  siteurl.com: [Blog]

  siteurl.com/category/example-category: [Blog > Example Category]

  siteurl.com/post/2015/entry-title: [Blog > Entry Title]

I've found this snippet which correctly outputs the breadcrumb for the entry permalink page:

Blog

    {% if craft.request.segments %}
        {% for crumb in entry.getAncestors() %}

{{ crumb.getLink() }}

        {% endfor %}

{{ entry.title() }}

    {% endif %}

But I also need something that will include a crumb for when the visitor is on a category page.

So far, my templates are structured like so:

templates/
 | index.html
 | _layout.html
 | posts/
    | index.html
    | category.html
    | _entry.html

Where the breadcrumb snippet is included in '_layout.html'.

In EE, I would just check my segments and use Low Seg2Cat to grab the category title. Is there an equivalent to this process in Craft? Or is it handled completely differently?

If your categories are only one level deep, you could hard-code the breadcrumbs into the category template:

{% block breadcrumb %}

Blog

{{ category.title }}

{% endblock %}

In _layout.html you would have:

{% block breadcrumb %}

Blog

    {% if craft.request.segments %}
      {% for crumb in entry.getAncestors() %}

{{ crumb.getLink() }}

      {% endfor %}

{{ entry.title() }}

    {% endif %}

{% endblock %}

Haven't tried this myself, but I think it would work - the category template would override the layout.

Of course, if you have multiple levels of categories, the intermediate levels won't be included, so it's not an ideal solution.


Category query returning one fewer items than requested I'm building a knowledgebase for a client. The client has asked for content to be restricted by category and then by user. This part is easy enough - the users now use the same category field as articles. However, the templating is proving troublesome.

Currently I'm querying for the category IDs, building an array and using it in the main category query.

{% set searchQuery %}[{% for category in currentUser.kb__category %}{{ category.id }}{% if not loop.last %}, {% endif %}{% endfor %}]{% endset %}

This returns, for example, [268, 270, 273, 276]

Consistently, the page is displaying all but the first category. This happens no matter what the first assigned category is.

{% for category in craft.categories
  .group('knowledgeBase')
  .id(searchQuery)
  .level(1)
  .all()
%}

If I replace searchQuery with [268, 270, 273, 276] it works perfectly, which is baffling me as that's what has been output.

If it works hard-coded, try trimming your variable:

set searchQuery = searchQuery|trim

OR, even better, build an array:

{% set categories = [] %}

{% for category in currentUser.kb__category %}
   {% set categories = categories|merge(category.id) %}
{% endfor %}

{% for category in craft.categories
  .group('knowledgeBase')
  .id(categories)
  .level(1)
  .all()
%}


Date changing algorithm Im working on a school website where the client would like a global date that is the start and finish of all the classes. This part is easy as I have made a Global where you enter the Start and End dates for the semester. At the moment this is just a text field.

The next challenge is to make it add days onto the start and end date depending on what day a class starts on.
So for example:
If I say the week starts on a Monday and set the starting date to the 20/10/2015. If the class is also on a Monday it will not change the date. But if the class is a Tuesday it will add +1 to the date making the starting date the 21st. (Wednesday +2, Thursday +3, Friday +4, Saturday, +5, Sunday +6) This would be easy except that if the day goes above how many days there are in a month. for example if the starting date is 28/10/2015 on Friday it would list as 32/10/2015 but would need to be changed to the 01/11/2015.

Does anyone know of a way that I can write this? Would using the date field make this easier?

Yes, a date field is a good idea. For the following example I'm using a date field "startDate" in a global set "classes". And for the classes entries I set up a dropdown field "weekday" with values "monday, thuesday, ..." and localized labels "Montag, Dienstag, ...".

Twig's date_modify filter does all the calculation for this:

{% set weekday = entry.weekday %}
{% set classDate = classes.startDate|date_modify(weekday) %}

{{ classDate|date('l, F j, Y') }}


db query to get fields related to entry Sorry if this question is starting off too abstract. I'm porting a calendar plugin from Textpattern and WordPress into Craft.  Basic workflow for the output has been (in twig terms):

{% set start = "now"|date("Y-m-d") %}
{{ craft.Calendar37.calendar_full(start)|raw }}

and the plugin php does all the work of querying the db and producing the calendar.

What I'm up against is getting the db query right. It seems pretty abstract to get all the fields related to an entry--in particular working out the query to get the category from a category field in the entry. Probably I can work that out, but here's my question:

Would it be possible or better to do more of the work with Twig, and less in php?  I.e. once the php db query knows the entries and i could put that into (I suppose) a model, then can Twig figure out the rest using (I haven't tried this, just working it out in my mind):

{% set start = "now"|date("Y-m-d") %}
{% craft.Calendar37.initialize(start) %}  {# just does the DB query #}

  ...

    {% set event_instances = craft.Calendar37.getInstances(date) %}
    {% for instance in event_instances %}
       {% set entry = craft.entries.id(instance.entryId) %}

             {{ instance.time }} - {{ craft.entries.id(instance.entryId).title }}

    {% endfor %}

I wonder about efficiency.  One big, but precise query in php is probably better than going back from twig for every event on each day of the month as shown in the second part here.  This is the query so far; it doesn't find the category, or slug, or several other things yet:

$events = $query
    ->select('*') //c37.event_id, dateYmd, timestr, alt_text, css_class, entries.id as event_id, title as event_title, slug')
    ->from('calendar37 c37')
    ->join('entries entries', 'c37.event_id = entries.id')
    ->join('content content', 'entries.id = content.elementId')
    ->join('elements_i18n elements_i18n', 'entries.id = elements_i18n.elementId')
    ->where("c37.dateYmd >= $fromDateYmd")
    ->andWhere("c37.dateYmd <= $toDateYmd")
    //->andWhere('STATUS = published, pending, etc')
    ->order('dateYmd ASC, timestr ASC')
    ->queryAll();

Thanks for any advice!

I wonder about efficiency.

You're right to worry.  Doing this from PHP (even if you break it up into multiple SQL queries to get the data you need) is going to be much faster and less resource intensive than doing it from Twig.

One thing I'd look at though, instead of querying data directly against the database, is to see if you can get what you need going through Craft's services in craft/app/services/.

That way you don't have to worry about your plugin breaking in the event that the underlying database structure changes during an update.


How to list entries related to a category + related to a section? Sorry if this has been asked before. I've searched for other relatedTo questions but could not find anything similar.

I have 2 sections (each having 1 entry type):

games
reviews

Games are linked to 1 or more categories using a Categories field.
Reviews are linked to 1 or more games using an Entries field.

On a category page I can list all related games using:

craft.entries({section: 'games'}).relatedTo(category)

I do however want to list all games inside a category that have at least 1 review. I tried something like

craft.entries({section: 'games'}).relatedTo(category).relatedTo(craft.entries.section('reviews'))

but that lists all games having a review regardless of the category. How to solve this?

When you call this:

craft.entries({section: 'games'}).relatedTo(category).relatedTo(craft.entries.section('reviews'))

that second relatedTo param is just overriding the first one. Lucky for you, that parameter does accept multiple criteria (see the “Passing Multiple Relation Criteria” section on http://buildwithcraft.com/docs/relations#the-relatedTo-param).

{% set games = craft.entries({
    section: 'games',
    relatedTo: ['and',
        category,
        craft.entries.section('reviews').status(null)
    ]
}) %}

It's a good idea to specify that category will be a target element (where the Games entries did the selecting), and that the Reviews will be source elements (where the Games were selected by the Reviews), as this will slim the DB query down a bit:

{% set games = craft.entries({
    section: 'games',
    relatedTo: ['and',
        { targetElement: category },
        { sourceElement: craft.entries.section('reviews').status(null) }
    ]
}) %}


Element-API migration - entries by category I am having trouble getting the related category passed thru to the entry api endpoint.

I cant use :

   $criteria = craft()->elements->getCriteria(ElementType::Category);
        $criteria->id = $catId;
        $category = $criteria->first();

What is the equivalent in craft 3 api v2?

'api/v1/ship/category/<catId:\d+>.json' => function($catId) {
//old api craft 2
        $criteria = craft()->elements->getCriteria(ElementType::Category);
        $criteria->id = $catId;
        $category = $criteria->first();

//api craft 3
        return [
            'elementType' => Entry::class,
            'elementsPerPage' => 30,
            'criteria' => [
                'criteria' => ['section' => 'ship'],
                'relatedTo' => ['targetElement' => $category],
            ],
            'transformer' => function(Entry $entry) {
                return [
                    'title' => $entry->title,
                    'id' => (int) $entry->id,
                    'slug' => $entry->slug,
                    'postDate' => $entry->postDate
                ];
            },
            'pretty' => true
        ];
    },

Solved it like this:

//categories
    'api/v1/ship/category/<catId:\d+>.json' => function($catId) {
        return [
            'elementType' => Category::class,
            'criteria'    => ['id'   => $catId],
            'paginate'    => false,
            'transformer' => function(Category $category) {
                $entries = Entry::find()->relatedTo($category)->all();

                $en=[];
                foreach($entries as $entry) {

                    //Final return
                    $en[]= [
                        "type" => "shipItem",
                        'sendtoseafarerhelp' => $entry->sendToSeafarerHelp,
                        'title' => $entry->title,
                        'url' => $entry->url,
                        'categoryTitle' => $entry->shipCategory[0]->title,
                        'categorySlug' => $entry->shipCategory[0]->slug,
                        'categoryUrl' => $entry->shipCategory[0]->uri,
                        'summary' => $entry->shipIntroText,
                        'descripton' => $entry->shipDescription,
                        'pdfs' => $pdfs,
                        'thumbs' => $thumbs,
                        'sponsors' => $sponsors
                    ];
                }

                return [
                    'title'   => $category->title,
                    'entries' => $en
                ];
            }
        ];
    },


Querying for an exact match on a Matrix block field with multiple types I'm trying to query against a specific field value in a Matrix field with multiple block types, and I've tried multiple approaches with no success. It either returns 0 results, or all blocks regardless of type.

The use case is that Snipcart is doing a callback with the ordered items and their skus. I got the different product variants in a Matrix fields, and every variant has its own sku. The field have two block types. I want to find the correct product variant and reduce the available stock.

The simplest approach is this:

$criteria      = craft()->elements->getCriteria(ElementType::MatrixBlock);
$criteria->sku = 'JW';

I figured out that it won't join the content table if you don't specify a fieldId, and you also need a typeId.

$criteria      = craft()->elements->getCriteria(ElementType::MatrixBlock);
$criteria->fieldId = $fieldId;
$criteria->typeId = $typeId;
$criteria->sku = 'JW';

What happens then is that it's seem to do the correct query, but with a AND query for the field on both block types (even though I have defined a typeId):

system.db.CDbCommand.query(SELECT `elements`.`id`, `matrixblocks`.`fieldId`, `matrixblocks`.`ownerId`, `matrixblocks`.`ownerLocale`, `matrixblocks`.`typeId`, `matrixblocks`.`sortOrder`
FROM `craft_elements` `elements`
JOIN `craft_elements_i18n` `elements_i18n` ON elements_i18n.elementId = elements.id
JOIN `craft_matrixcontent_colorsandtextures` `content` ON content.elementId = elements.id
JOIN `craft_matrixblocks` `matrixblocks` ON matrixblocks.id = elements.id
WHERE (((((((elements_i18n.locale = :locale) AND (content.locale = :locale)) AND (elements.archived = 0)) AND (elements.enabled = 1)) AND (elements_i18n.enabled = 1)) AND (content.field_texture_sku=:contentfield_texture_sku1)) AND (content.field_color_sku=:contentfield_color_sku1)) AND (matrixblocks.fieldId=:matrixblocksfieldId1)
GROUP BY `elements`.`id`
ORDER BY `matrixblocks`.`sortOrder` LIMIT 100. Bound with :locale='en_us', :contentfield_texture_sku1='JW', :contentfield_color_sku1='JW', :matrixblocksfieldId1='15')

The key here is the fact that my typeId isn't being applied, and this part:

(content.field_texture_sku=:contentfield_texture_sku1)) AND (content.field_color_sku=:contentfield_color_sku1))

I would like to query for a match independent of what type it is, as the blocks can be either or. Is there a way I can turn that into a OR query?

When I understand Brandon correctly in this answer Query for blocks across Block Types using the new field parameter?, it's not possible to set up what you want with a criteria model.

What you can do though is to add additional custom query conditions to the dbCommand after running the criteria model through the buildElementsQuery function.

public function getMatrixBlocks($matrixFieldId, $fieldValue)
{
    $criteria = craft()->elements->getCriteria(ElementType::MatrixBlock);
    $criteria->fieldId = $matrixFieldId;

    $dbCommand = craft()->elements->buildElementsQuery($criteria);

    $params = array(
        ':myFieldHandle' => $fieldValue,
    );

    $conditions = array('or',
        'content.field_myBlockTypeA_myFieldHandle=:myFieldHandle',
        'content.field_myBlockTypeB_myFieldHandle=:myFieldHandle',
    );

    $dbCommand->andWhere($conditions, $params);

    return $dbCommand->queryAll();
}


Hiding specific items from public So I want to hide certain items if a user is not logged into the website. I already have a custom lightswitch field on each of the items but I'm not sure on how to write the code for it. Can anyone help?

Based on https://craftcms.com/docs/lightswitch-fields and https://craftcms.stackexchange.com/a/352/5134:

{% if entry.lightswitchFieldHandle %}
    {% if currentUser %}
        Display entry that only logged users can see
    {% endif %}
{% else %}
    Display entry that anyone can see
{% endif %}


Uploading animated GIF outputs only first frame I've updated everything to the latest version and the result of uploading an animated GIF is just the first frame of the animated GIF.

Any ideas on why animated GIFs aren't working? Is there a way to disable image transforms for animated GIFs or GIFs in general?

PHP 5.4.45-0+deb7u1
ImageMagick 6.7.7-10
Craft Pro 2.4.2692

Thanks!

Your ImageMagick library version is 3.5 years old.  I'd start by updating that to something newer.

You didn't list the PHP Imagick extension version, but I'd bet it's out of date as well.  3.1.2 is the latest stable release.

Also, Craft will automatically try and detect if Imagick is installed and available via PHP, but it won't hurt to explicitly set the imageDriver config setting to imagick to be sure.

  Is there a way to disable image transforms for animated GIFs or GIFs in general?

Not currently, sorry.


Plugin Store install buttons are not visible I'm just working on a dev site and my Plugin install buttons are gone. I'm not sure how long they've been gone either, I don't really know where to start to debug it.

No errors in the console and I have run composer update to make sure I'm all up to date, too.

Below is an image of where the 'install' button should be in the plugin store.

Most likely you have the allowUpdates config setting in your config/general.php file set to false.


How to filter entries with null value in date field? I have date field in entry that is empty therefore has null value.
I'd like to filter entries that have date field value equal to null.
How would I set that parameter on element criteria object? I don't want to achieve it by looping yet because I'm merging entries from another section.

Setting it to null returns entries with or without value.
{% set myEntries = craft.entries.section("mySection").date(null) %}

Setting it to "" returns entries with or without value.
{% set myEntries = craft.entries.section("mySection").date("") %}

The special strings :empty: and :notempty: might be what you're looking for. The docs list it only against expiryDate, but I think it's available for any field: https://docs.craftcms.com/v3/dev/element-queries/entry-queries.html#expirydate


Error with Craft CMS set up and composer: failed: SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: YES) Hi I am trying to set up craft CMS with composer. I am using MAMP on a mac and I just cannot get it to connect. I get this error even though I know the password is correct.
failed: SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: YES)

I have tried setting up a new user with new password and ensure full access privileges are set up on that database but I get the same error. I have tried setting up a separate host but when I try and run the Craft CMS set up with that I get this error:
Testing database credentials ... failed: SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: nodename nor servname provided, or not known

Any help with this would be much appreciated as I've wrestled with it all day now. Thanks.

I am also using MAMP on a Mac, and had similar issues first setting up. There are a few things to check.
Under your host settings, use the traditional ports instead of MAMP's custom ports, and set your servers to run as your local Mac user.

Then on the MySQL settings window, make sure to allow incoming connections, and check the box to include it in "group start". You can also confirm it's on the right port, here, in the upper right.
(I also suggest using MAMP to change the MySQL root user password - I set it to root which is the MAMP default.)

Lastly, make sure you and MAMP are both using the same MySQL!  If you have it installed via homebrew as well, then you might not be running the same as MAMP does. On the command line, you can use the one in MAMP via:
/Applications/MAMP/Library/bin/mysql -h localhost ...
Assuming you're using the defaults, first, Run ./craft setup and use the following:
Database driver: mysql
Database server: localhost
Database port: 3306
Database username: root
Database password: root
There are also custom backup and restore commands that work better for MAMP and Craft CMS which you might find helpful.


Help debugging "An unknown error occurred." Recently, when I edit categories or entries I get the dreaded "An unknown error occurred." When I check the logs I see:

2017/12/11 20:41:51 [error] [exception.Craft\HttpException.403] Craft\HttpException in /srv/users/serverpilot/apps/0default/craft/app/services/UserSessionService.php:329

Not quite sure where to go from there. 403 makes it look like a permissions issue but my permissions are all setup just like I normally have them (744). Anyone got any ideas?

https://github.com/craftcms/cms/tree/master-v2/src/services/UserSessionService.php#L325

The error is thrown when you don't have the permission to change/do something. Your file permissions do not matter it is about the permissions in craft. Are you not admin? Could you tell us if you are a normal user and don't have certain permissions? Maybe another member of your team changed something?

Do you have any plugins installed that have any hooks/events?
Do you have the latest Craft version?


Add Checked Attribute to Custom User Fields on Frontend User Form I have a multi-select for users to sign up for newsletters.
When they edit their profile they need to be able to see which newsletters they are already signed up for. I have the code to output the entire options list or just the ones that they have selected but I haven't figured a way to add the selected attribute to the ones the user has selected.

{% set newsletters = craft.fields.getFieldByHandle('newsletters') %}
<select multiple>
    {% for opt in newsletters.settings.options %}
        <option value="{{ opt.value }}" >{{ opt.label }}</option>
    {% endfor %}
</select>

The "for opt in newsletters.settings.options" can be changed to "for opt in newsletters.settings" to show just the ones the user has already selected.

Solved!

{% for letter in currentUser.newsletters.options %}
    <input type="checkbox" value="{{ letter.value }}" name="{{ letter.value }}" id="{{ letter.value }}"
        {% if letter.selected == true %}checked="checked" {% endif %}/>
    <label for ="{{ letter.value }}">{{ letter.label }}</label>
{% endfor %}


provide a 'back' or 'cancel' or 'close' button to return to whatever page that particular template was accessed from I have two templates. For the purpose of this question lets say the first template is step 1, and the second is step 2.
There are links to launch these templates all over the site, but some times an entry is defined and sometimes its not. if the entry is defined, step 1 is skipped.
On both steps I have a 'close/cancel' button. I need these buttons to go to whatever url the user was on when they 'launched' this process.

Is there a way of storing a URL as a variable when the 'launch' button is clicked even after moving from step 1 to step 2?

see user journey diagram:

You could use the Cookies plugin to store the last visited URL before the user hits one of the "step" templates, i.e. by putting something like the following in every template where the links to the "steps" template occurs:

{{ setCookie( 'lastUrlBeforeStepStuff', craft.request.url) }}

Then, inside your "step" templates, you could render the "cancel" links like this:

Cancel


Getting the URI of an Entries field in a Structure with no URLs I am building a navigation section which is a structure. The idea is that it is a flexible place to build links to other entries/ custom urls etc. It has one entry.type called page which has an entries Field called 'entryLink' to link to other entries.

It has no urls of its own set in 'Entries in this section have their own URLs'.

When i try to get the entriesField called 'entryLink' all i can get is the title:

 {% set navEntries = craft.entries.section('navigation').hidePage('< 1')  %}
   {% for nav in navEntries %}

 {{ nav.entryLink.first() }}

 {% endfor %}

If i try and get the slug or uri I always get an error. Eg when using :

 {% set navEntries = craft.entries.section('navigation').hidePage('< 1')  %}
   {% for nav in navEntries %}

 {{ nav.entryLink.first().uri }}

 {% endfor %}

I get

Impossible to access an attribute ("uri") on a null variable

What am I missing?
I notice the documentation here: https://craftcms.com/docs/entries-fields
specifies 'target locale' which i do not have in my entrie field setup.

So this is what worked for me. It's a bootstrap drop-down menu system using the nav tag from the structure 'menu' with custom fields as described above

{% set menu = craft.entries.section('menu').hidePage('< 1') %}
{% set navlink = "" %}

{% nav entry in menu %}
    {% if entry.entryLink.first|length %}
    {% set navlink = entry.entryLink.first.uri %}
    {% else %}
    {% set navlink = entry.customMenuUrl %}
    {% endif %}

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

            {{ entry.title }}

                {% for child in entry.getDescendants().hidePage('< 1') %}
                {% if child.entryLink.first|length %}

 {{ child.entryLink.first.title }}

                {% endif %}
                {% endfor %}

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

{{ entry.title }}

    {% endif %}

{% endnav %}

This has managed to produce a bootstrap drop down menu from the nav tag on a structure section with two fields: customMenuUrl (plain text) and entryLink (Entries field)


Anyone with a tricked out .htaccess file I am looking at shaving www. and enforcing https on the entire site without a plugin.  All along removing the index.php.

Here is my .htaccess file, it works but is it optimized.  If you have any suggestions on how to condense or streamline would like to hear or see an example please. Thanks!

<IfModule mod_rewrite.c>

RewriteEngine On

# Remove WWW and SSL enforce
RewriteCond %{HTTP_HOST} ^www.example.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Send would-be 404 requests to Craft
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
RewriteRule (.+) index.php?p=$1 [QSA,L]

</IfModule>

Been using this one for years, works great:

<IfModule mod_rewrite.c>
    RewriteEngine On

    # ========================================= #
    # Force website to use "www"
    RewriteCond %{HTTP_HOST} ^example.com [NC]
    RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301]
    # ========================================= #

    # ========================================= #
    # Force website to use "https"
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=301]
    # ========================================= #

    # ========================================= #
    # Send would-be 404 requests to Craft
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
    RewriteRule (.+) index.php?p=$1 [QSA,L]
    # ========================================= #

</IfModule>

This one adds www, but it's simple to reverse that (as you do in your original example).


How do I change the value of a select box field of a certain entry through the front-end? So I'm having this entry (a product) that contains a selectbox field with two values:

Reserved
Available

By default this field is set to 'Available', but when the user lands on a certain page (a thank you page after "ordering" this product with the entry id as a querystring in the URL), I'd like to change the value of that selectbox to 'Reserved'.

Anyone can put me in the right direction on this one?

Thanks in advance!

Twig
You can check for certain URL parameters via
{% set param = craft.app.getRequest().getParam('id') %}
{% if param is not null %}
    {% set entry = craft.app.getElements().getElementById(param) %}
    {# insert your new field value! not the label, the value/handle
    {% do entry.setFieldValue('fieldHandle', 'Reserved') %}
    {% do craft.app.getElements().saveElement(entry) %}
{% endif %}

However I would not recommend doing this in Twig
PHP
You can see how to use Template Variables and create your boilerplate at pluginfactory.io
{% do craft.myAwesomePlugin.saveEntry(entry, {fieldHandle: 'yourValue'}) %}

And your function could be
public function saveEntry($entry, $attributes = []){
    $entry->getContent()->setAttributes($attributes);
    craft()->entries->saveEntry($entry);
}

That's just a "quick" version, I suggest you to take a look at EntriesController to see how Craft handles it in detail


How can I use a where statement with grouped results? I am grouping entries that have the same date together so that I only get a single date. Works great.

I would like to loop through each entry that has that date and I'm not having much luck. I want to show

Here is what I have so far:

{% for date, attempt in attempts|group('attemptDate') %}

        {{ date|date('M j, Y') }}
        {% if type == 'My Type' %}
            {# Get all entries where type = My Type & entry.attemptDate = date. #}
            {% set total = 0 %}
            {% count = 0 %}
            {% for ?? in ?? %} {#
                {% total = loop.index %}
                {% count = {# if value in myField is true #} %}
                {{ count }}/{{ total }}
            {% endfor %}
        {% endif %}

{% endfor %}

Thank you for any suggestions!

This should work:

{% for date, attempt in attempts|group('attemptDate') %}

      {{ date|date('M j, Y') }}
      {% for entry in attempt %}
        {% if entry.type == 'My Type' %}
          {{ entry.title }}
        {% endif %}
      {% endfor %}

  {% endfor %}

I don't know what you want to do with the 'type' of the entries?
But if you want to limit the amount of entries according to type, you could fill "attempts" with all entries of a certain type first and then loop through them. Than you could remove the if statement which would be cleaner and faster I think.

So something like:

{% set attempts = craft.entries.section("something").type("My Type").find() %}


Search/Filter Freeform submissions by field value I need to be able to get a count (in the frontend) of the number of submissions that have a field with a specific value. I don't need the submitted data of the submissions, just the count of submissions whose data matches a specified value.

This code returns the total number of submissions:

{% set submissionCount = craft.freeform.submissions({
    form: 'myAmazingForm'
}).count %}

I tried using the native Craft search parameter, but it returns zero:

{% set submissionCount = craft.freeform.submissions({
    form: 'myAmazingForm'
}).search('fieldWithValue:123').count %}

And yes, there are submissions that would match that.

How can I do this?

This might not work, but you can try it like so:

{% set submissionCount = craft.freeform.submissions({
    form: 'myAmazingForm',
    fieldWithValue: '123',
}).count() %}


Main email address for "Contact Us" in settings is not changing we have a contact section on our website which is going to an info@ email address.  I need to change this to my email.  I have gone to Globals - Settings - Email address and changed it there, but when I sent a test email it didn't work.  Could you please tell me if I need to try a different section?  Thanks!

If you are using the popular 'Contact Form' plugin, try Settings > Contact Form (under Plugins heading) and the field you want is the first field, 'To Email'.
The variables in Globals are 100% custom but usually change the email address that is displayed sitewide such as in your footer or contact page. They can be, but are not necessarily, wired into your contact form.
If you can't see Settings in the left side nav, or the Plugins section in Settings, you may need to request greater permissions from your CMS admin.
Be gentle (mods), this is my first answer in a long time ;)


Custom route with optional tokens I have a question about custom routes set in routes.php. Can route segment be optional?

Taking example from docs - 'blog/archive/<year:\d{4}>' => 'controller/action/path', can we make year token optional in url and still match route when someone vists blog/archive?

Short and sweet... I think you just need to add a second route.

'blog/archive' => 'controller/action/path',
'blog/archive/<year:\d{4}>' => 'controller/action/path'


Pictures (Assets) not showing (error 404) My pictures were not showing - even if everything looked great (files were available at the right place, template code was correct, ...). My first reaction was to check the htaccess file, but (see my answer below).

I called my directory "icons" (www.example.com/icons/) which was obviously not a good idea. After renaming the directory to "img/icons" it works perfect!


Why would Craft produce a template loader error (TemplateLoaderException) when rendering its default error pages? I'm getting a Template Loader Exception when I hit a 404 on my site:

Craft\TemplateLoaderException

Unable to find the template “error”. (/craft/app/etc/templating/twigextensions/TemplateLoader.php:123)

#0 /craft/app/etc/templating/twigextensions/TemplateLoader.php(71): Craft\TemplateLoader->_findTemplate('error')
#1 /craft/app/vendor/twig/twig/lib/Twig/Environment.php(312): Craft\TemplateLoader->getCacheKey('error')
#2 /craft/app/vendor/twig/twig/lib/Twig/Environment.php(378): Twig_Environment->getTemplateClass('error', NULL)
#3 /craft/app/etc/templating/TwigEnvironment.php(23): Twig_Environment->loadTemplate('error', NULL)
#4 /craft/app/vendor/twig/twig/lib/Twig/Environment.php(347): Craft\TwigEnvironment->loadTemplate('error')
#5 /craft/app/services/TemplatesService.php(225): Twig_Environment->render('error', Array)
#6 /craft/app/controllers/BaseController.php(74): Craft\TemplatesService->render('error', Array)
#7 /craft/app/controllers/TemplatesController.php(201): Craft\BaseController->renderTemplate('error', Array)
#8 /craft/app/framework/web/actions/CInlineAction.php(49): Craft\TemplatesController->actionRenderError()
#9 /craft/app/framework/web/CController.php(308): CInlineAction->runWithParams(Array)
#10 /craft/app/framework/web/CController.php(286): CController->runAction(Object(CInlineAction))
#11 /craft/app/framework/web/CController.php(265): CController->runActionWithFilters(Object(CInlineAction), Array)
#12 /craft/app/framework/web/CWebApplication.php(282): CController->run('renderError')
#13 /craft/app/framework/base/CErrorHandler.php(368): CWebApplication->runController('templates/rende...')
#14 /craft/app/etc/errors/ErrorHandler.php(281): CErrorHandler->renderError()
#15 /craft/app/framework/base/CErrorHandler.php(351): Craft\ErrorHandler->renderError()
#16 /craft/app/framework/base/CErrorHandler.php(218): CErrorHandler->renderException()
#17 /craft/app/etc/errors/ErrorHandler.php(145): CErrorHandler->handleException(Object(Craft\HttpException))
#18 /craft/app/framework/base/CErrorHandler.php(131): Craft\ErrorHandler->handleException(Object(Craft\HttpException))
#19 /craft/app/framework/base/CApplication.php(740): CErrorHandler->handle(Object(CExceptionEvent))
#20 [internal function]: CApplication->handleException(Object(Craft\HttpException))
#21 {main}

I haven't added a custom 404 error page, or changed the error template paths in my config, so I would expect Craft to serve up its default error page.

What gives?

As it turns out, I had made a configuration change that broke Craft's default behavior:

'defaultTemplateExtensions' => array('twig', 'xml')

All of Craft's internal templates use .html, and HTML templates are included in the default value of that config item. By overriding it, I had rendered Craft unable to find its stock error template.

Moral of the story — When you override defaultTemplateExtensions, make sure to include the default file extensions ('html','twig') in the new list that you set.


find which template is used in given website? I want same template which is used in http://www.rideicon.com/ this website...is there any way to find which template is used in given website?

Craft CMS does not really have ready to use templates. This is why you should not be able to find any references to that. In difference to Wordpress, etc. – usually these are hand-crafted. Is this what you were asking?


How do I redirect traffic from a legacy category URL to a new category URL? Within Craft, I am renaming the top-level entry URL format for a section from legacy-subdirectory/{slug} to new-subdirectory/{slug}. How do I redirect traffic from the legacy URL to the new format within Craft?

I am aware that I may use the rewrite rule within .htaccess in exchange for a slight performance hit:

    RewriteRule ^legacy-subdirectory/(.*)$ /new-subdirectory/$1 [R=301,NC,L]

I would prefer handling this within Craft. As there is only one slug in which I need the redirect, I would prefer handling this without plug-ins.

There are a few plugins which can handle this, but Retour is the newest and shiniest!

  https://github.com/nystudio107/retour

It's from the same developer as SEOmatic... he puts a lot of love & attention into his plugins, so you know it's safe to rely on.


relatedTo using product type? Is there a way to dynamically get all the related products based on the product type?

I seem to be getting all the products regardless of product type when I use:

{% set products = craft.commerce.products.relatedTo(category).order('postDate desc') %}

(obviously since I don't have any categories).

I'm a little unclear but I think you're looking for:

{% set products = craft.commerce.products.type('productTypeHandle').order('postDate desc') %}


Random posts displayed but exclude current entry ID I am brand new to Craft and can't find much support on this problem online. I have my entry pages and at the bottom of them, I have a div with the code below in it which randomly links to any entry.

I now would like this to disallow the entry that I am on from that randomization. I assume from other threads it would be something to do with finding the ID of the entry the user is on and not allowing it in the randomize?

{% for image in randomEntry.projectFeaturedImage %}

    {{ randomEntry.title }}
    See Project

{% endfor %}

Here are a couple of useful stackexchange questions

Getting a random entry: Section entries - order by random
Excluding the current entry: Exclude Current Entry

Putting that together:

{% set randomEntry = craft.entries({
  id: 'not '~entry.id,
  order: 'RAND()'
}).first %}

This will fetch entries whose id is not entry.id (entry is the current entry), ordered randomly, and then give you the first of those.

Probably you want to specify the section or sections to fetch your entries from:

{% set randomEntry = craft.entries({
  section: ['thisSection', 'thatSection', 'theOtherSection'],
  id: 'not '~entry.id,
  order: 'RAND()'
}).first %}

This will do the same thing, but only fetch entries from those 3 sections.

After all of that, you should also be sure to test that there actually is an entry:

{% if randomEntry %}
  ... do your thing ...
{% endif %}


Identify immediate siblings block type in matrix I have a type of content that i use on the homepage of a site I am building, the code is shown here:

    {% for point in entry.keyPoints %}

{{ point.heading }}

                {{ point.text }}

    {% endfor %}

This does exactly what i want it to do. It opens a UL and then loops through the different items which are LI's and output accordingly.

I want to use this same type of content on inner pages however as a matrix block TYPE rather than being the only type of content like on the homepage in the above example.

The problem then is that the FOR loop starts before i even know if this is the type of content i am dealing with so I can't appropriately wrap this type in a UL.

I can solve this by checking if it is the FIRST of TYPE and LAST of TYPE and outputting the opening and closing UL tags that way.

I then run into another problem that the first and last of this type are not necessarily adjacent to each other. If that is the case then all the other content TYPEs in the matrix between the FIRST and LAST of this TYPE will be inside of the UL as well.

My question then is how can i determine if the other matrix blocks that are immediately adjacent to this TYPE are of the same TYPE and if they are don't close the UL and if they are NOT then close the UL.

My code to determine what type is is just a simple FOR loop and then inside it a series of conditionals checking the TYPE and then outputting the appropriate content accordingly.

Fun question! :)

You can use getNext() and getPrev() Methods on the MatrixBlockModel documentation page.

{% for point in entry.keyPoints %}

    {# if this is the "typeToWrap" block type #}
    {% if point.type == 'typeToWrap' %}

        {# if there is a previous point to check #}
        {% if point.getPrev() %}

            {# if the previous point wasn't the "typeToWrap" type start a ul #}
            {% if point.getPrev().type != 'typeToWrap' %}

            {% endif %}

        {# if there isn't a previous point start a ul #}
        {% else %}

        {% endif %}

    {% endif %}

    {# output point #}

    {# if this is the "typeToWrap" block type #}
    {% if point.type == 'typeToWrap' %}

        {# if there is a next point to check #}
        {% if point.getNext() %}

            {# if the next point isn't the "typeToWrap" type end a ul #}
            {% if point.getNext().type != 'typeToWrap' %}

            {% endif %}

        {# if there isn't another point end a ul #}
        {% else %}

        {% endif %}

    {% endif %}

{% endfor %}


Settings in Admin Panel Blank Have kind of a weird problem going on with my site, which I just moved over from my staging server to production. Originally, everything looked fine, except I couldn't get into the Admin Panel. I discovered that I had an old .htaccess file in my root directory, and once I replaced that with the Craft CMS one, I was able to login just fine. Now, however, I've noticed that while most of the options on the left (Assets, Entries, Categories, etc) work as expected, if I select Settings, I'm greeted by a blank page. Any ideas?

My previous question as mentioned.

There's a chance that one of your plugins is causing this behavior. Go into your craft_plugins table, and change the value of enabled to 0 for every single plugin.

If your Settings page is then accessible, cautiously re-enable each plugin one-by-one. This will help you hone in on which plugin may be causing the problem.


Access Element API JSON in another environment First Craft project and off to a great start. I don't think i'll ever touch Wordpress again. :)

I'm using the Element API plugin to build out one of my feeds of entries and hoping to use that on a couple sites as a little widget.

JSON: https://csgoevents.gg/api/events.json

Using jQuery for now: http://codepen.io/eboyer/pen/kXqNXJ

Getting this error: "XMLHttpRequest cannot load . No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '' is therefore not allowed access."

Historically, i'm more of a designer/html/css developer, so HTTP & API work is new to me. From what I understand this can be avoided if the server could return JSONP? Or if I had any sort of control over nginx configurations? (I'm hosting with Web Faction)

Are there any examples out there of using Element API data on other domains?

Hopefully its something with a quick solve. Thanks in advance, excited to be here!

Brandon answered this in a github issue https://github.com/pixelandtonic/ElementAPI/issues/4

You can do that by setting your endpoint config to an anonymous function:

'my/endpoint/pattern' => function() {
    HeaderHelper::setHeader([
        'Access-Control-Allow-Origin' => 'http://example.com'
    ]);

    return [
        // ...
    ];
}


How can I retrieve older versions of a custom entry type in bulk? I am building an API that returns instances of an entry type. Only authenticated users can access the API. There are different tiers of user - paid and free. Free users can access the API, but the content should only be updated weekly. I have a scheduled task that regularly updates my entries.

How can I query the database for a particular entry type, but only retrieve versions of entries that are at least 7 days old?

Okay, here's my stab at this. No doubt Brad will swagger in at some point, and declare that this can all be done with one line of trivial PHP.

Whatever, Brad. Moving on...

You can't use the ElementCriteriaModel to retrieve specific entry versions. This leaves you with two options:

Option 1: Use the Entry Revisions service

The EntryRevisionsService has a getVersionsByEntryId method, which does precisely what it says. If you're only dealing with a small number of Entries, this may suffice.

Option 2: Go old(ish) school

If the first option doesn't suit, you'll need to get your hands dirty querying the database, and populating EntryModel instances from the result.

Here's an example, to get you started:

$versionIds = [];

// Retrieve all the versions created before your "threshold" date.
$versions = craft()->db->createCommand()
    ->select(['ev.entryId as entryId', 'ev.id as versionId'])
    ->from('entryversions ev')
    ->where('ev.dateCreated < :date', [':date' => '2017-03-20'])
    ->order('ev.dateCreated desc')
    ->queryAll();

/**
 * Construct an associative array where the key is the entry ID,
 * and the value is the most recent entry version ID created _before_
 * your date threshold.
 */
foreach ($versions as $version) {
    if (!array_key_exists($version['entryId'], $versionIds)) {
        $versionIds[$version['entryId']] = $version['versionId'];
    }
}

/**
 * Finally, we can do something useful with our lives.
 * Retrieve the desired version of the entries.
 *
 * Note: you'll need to retrieve all of the required entry
 * columns, in order to populate your EntryModel. I've just
 * done a wildcard, you may wish to be more specific.
 */
$results = craft()->db->createCommand()
    ->select('e.*, ev.*')
    ->from('entries e')
    ->join('entrytypes et', 'et.id = e.typeId')
    ->join('entryversions ev', 'ev.entryId = e.id')
    ->where('et.handle = :handle', [':handle' => 'entryTypeHandle'])
    ->andWhere(['in', 'ev.id', array_values($versionIds)])
    ->group('e.id')
    ->order('ev.dateCreated desc')
    ->queryAll();

Now that you've retrieved the results, you'll need to convert each row to an EntryModel. This could be fairly trivial, or a living hell, depending on whether your Entries contains Matrix fields, Relationships, and so forth.

Note: I don't think it's possible to do this in a single query, but your GROUP BY fu may be better than mine.


Show Entries Based on Category - Localised Site I have the following code to display entries based on a single category:

{# Identify the primary category you want #}
{% set cat = craft.categories.title('events').level(1).first() %}

{# Grab an array of entries related to the primary category #}
{% set entries = craft.entries.section('projects').relatedTo(cat).find() %}

{% for entry in entries %}

{{ entry.title }}

{{ entry.subtitle }}

  Learn more

{% endfor %}

This works fine for the home locale (en) but on the others it displays all entries regardless of whether the category has been applied to it or not.

The slugs for the different locales were not the same. Changed those and all fixed.


How to order categories in key/value for loop? This is what I'm trying to accomplish:

All categories displayed on one page, with entries returned from each.
Only six entries shown in each category.
Categories need to be in a specific order.

I've got the first two points working, but can't figure out how to change the order of the categories. Am I going about this the wrong way?

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

{% for category, catEntries in entries | group('categoryField.first().title') %}

    {% for entry in catEntries|slice(0,6) %}

    {% endfor %}

{% endfor %}

Using the group filter you will always end up with the sort order of your entries. So you would need to sort the entries by your categories field, but this probably doesn't work.

But you can do the following:

{# Get the categories related to my "entrySection" entries in custom order #}
{% set entries = craft.entries.section('entrySection') %}
{% set relatedCats = craft.categories.relatedTo(entries).order('customCatField desc') %}

{# Loop the categories #}
{% for category in relatedCats %}

    {# Get and loop through the 6 most recent entries related to this cat #}
    {% set relatedEntries = craft.entries.relatedTo(category).limit('6') %}
    {% for entry in relatedEntries %}
        ...
    {% endfor %}

{% endfor %}


Escape characters in format I'm trying to find a method of escaping characters in Craft's DateTime object.

This is the output I'm trying to achieve: 16th January 2016

This is what I've tried: {{ article.postDate.format('j\<\s\u\p\>S\<\/\s\u\p\> F Y') }}

This is the output: 16&lt;00000000p&gt;th<!--00000000p--> January 2016

I can achieve the output by appending output together but there has to be a better way of achieving this than the following:

{{ article.postDate.format('j') }}<sup>{{ article.postDate.format('S') }}</sup> {{ article.postDate.format(' F Y') }}

Any pointers to documentation would be appreciated.

After trial and error I figured out you can escape characters using double backslash.

{{ article.postDate.format('j\\<\\s\\u\\p\\>S\\<\\/\\s\\u\\p\\> F Y') | raw }}

Outputs: 14th January 2016

In search of documentation I found a mention of double-escaping regular expressions due to Twig auto-escaping \. At this point I'm guessing this works for most Craft-Twig functions.


Craft equivalent to Drupal Signups module I'm investigating a switch to Craft CMS for my non-profit as an alternative to Drupal or Wordpress. We're on Drupal right now, and our website gets used daily to sign up for public events that we host.

The functionality of the Drupal Signups module (ttps://www.drupal.org/project/signup), combined with the Events module, is one thing we'd be want to replicate if we moved to another CMS. Essentially, we want to enable:

a) registration for the event (name, email address, phone number that is temporarily stored -- we don't want to deal with usernames or passwords to sign into the site)

b) a registration cap (i.e. registration closes at 40 attendees)

c) confirmation emails, as well as reminder emails to be automatically sent to registered users that the event is coming up

d) the ability for staff to send a group email to all registrants in case the event is delayed/cancelled from within the CMS;

e) the ability for our staff to view and manage signups from the admin interface (i.e. delete a registrant if they want to cancel their spot)

I see that Craft has plugins such as Venti to handle the event side of things. Is there anything currently available that could similarly handle signups and reminder notices? Does anyone know of similar examples using Craft CMS for other websites?

Thanks!

For the calendar portion:

Solspace Calendar: https://solspace.com/craft/calendar

Craft Calendars: https://topshelfcraft.com/calendars/introduction

For the membership part it'd be pretty easy to just add the people who register onto the event itself


Error 'form[fieldName] :  is invalid' while submitting multiple checkboxes I have a form with multiple checkboxes in it. However, when submitting the form it returns an error like this:

{"success":false,"errors":{"formDate":["Date is invalid."]}}

template:

<input type="hidden" name="fields[formDate]" value="">

{{ 'Select your date(s):' | t }}
{% for date in dateList.options %}
    <input :class="{ error: error['formDate'] }" type="checkbox" name="fields[formDate] []" value="{{ date.value }}">{{ date.label | t }}
{% endfor %}

I'm using Vue component to serialise the form. Checkbox field is posted as the array of checked values.

While searching the documentation I found only how to display the checkbox on the template. Probably the error is connected with the format of values passed through the AJAX call. Does anyone know the acceptable value format for the checkbox with multiple values?

I'm not sure if it can make a difference, but you should try to remove the white space between the two array in the name attribute.

Then I think you may have to format the date value with the date filter.

<label>
    <input :class="{ error: error['formDate'] }" type="checkbox" name="fields[formDate][]" value="{{ date.value|date('Y-m-d') }}">{{ date.label|t }}
</label>


API - Update Asset Volume Im trying to figure out how to move asset(s) to a different volume. Also if I move it will that affect the entries that are using the asset?

Here's what im using to target the asset:
$resourceImage = Asset::find()->volume('resourceImages')->filename($filename);

I need to move it to my productImages volume.

Thanks!

You can move them like this

$asset = Asset::find()->volume('resourceImages')->filename($filename)->one()
$folder = Craft::$app->getAssets()->findFolder(['volumeId' => X]);
Craft::$app->getAssets()->moveAsset($asset, $folder, $filename);

It won't change your relations or anything else in fact all the function does is:

/**
 * Move or rename an Asset.
 *
 * @param Asset $asset The asset whose file should be renamed
 * @param VolumeFolder $folder The Volume Folder to move the Asset to.
 * @param string $filename The new filename
 * @return bool Whether the asset was renamed successfully
 * @throws AssetLogicException if the asset’s volume is missing
 */
public function moveAsset(Asset $asset, VolumeFolder $folder, string $filename = ''): bool
{
    // Set the new combined target location, and save it
    $asset->newFilename = $filename;
    $asset->newFolderId = $folder->id;
    $asset->setScenario(Asset::SCENARIO_FILEOPS);

    return Craft::$app->getElements()->saveElement($asset);
}


Copy of subsite is still serving index.php in the links? I have 2 subsites on the same apache server both pointing to the same craft database.  The original subsite has the normal links, but, the subsite copy has index.php in all of the links.  Can someone point me in the right direction to remove the index.php references? NOTE: .htaccess is correct and the same on both sites.

You should have the setting 'omitScriptNameInUrls' => true on either both sites, or in the wildcard config.

<?php

return [
    '*' => [
        // ...
        'omitScriptNameInUrls' => true,
        // ...
    ]
];

You can read more about it here:
https://craftcms.com/support/remove-index.php


cartCookieDuration and purgeInactiveCartsDuration config settings How do I set the cartCookieDuration and purgeInactiveCartsDuration for only 24 hours?

If you go to the Commerce documentation for each (https://craftcommerce.com/docs/configuration#cartcookieduration and https://craftcommerce.com/docs/configuration#purgeinactivecartsduration), they both link to the PHP DateInterval class page that describes the various time formats you can use.

For 24 hours, either P24H or P1D should do it.


Deleted rows from elements_sites hunting stray slugs now I can't login Working on a migration up/down testing I went through and deleted TOO much from the element_sites table to remove unwanted slugs, not understanding really what's in there. Now I understand many elements are in there and I've deleted some vital stuff without a backup.
Is there a way to perhaps use these config/*.yaml files to rebuild the tables or something to that affect?
At the very least, when logging in my username and password no longer works, and forgot your password gives no joy. What a mess. Can the project be salvaged or am I looking at starting fresh?
I have time machine backups on my mac but as a docker newbie I didn't have the VM included in the backup. I believe the mysql data is all stored in the VM that nitro creates.

I'll post how I've begun to fix this. Since I couldn't login, I assume there was entries I removed from elements_sites relating to my user account. I did a query to see what elements I had that were not in elements_sites:
SELECT elements.id, elements.type
FROM elements
WHERE NOT EXISTS
    (SELECT *
     FROM elements_sites
     WHERE elements.id = elements_sites.elementId)
ORDER BY elements.id ASC

Which returned something like
1,craft\elements\User
8,craft\elements\Asset
10,craft\elements\MatrixBlock
12,craft\elements\MatrixBlock
13,craft\elements\GlobalSet
18,craft\elements\Asset
19,craft\elements\MatrixBlock
21,craft\elements\MatrixBlock
25,craft\elements\Asset
28,craft\elements\MatrixBlock

Seeing that my User element was missing, I created a new entry in elements_sites for it:
INSERT INTO nitro.elements_sites
    (id, elementId, siteId, slug, uri, enabled, dateCreated, dateUpdated, uid)
VALUES
    (1, 1, 1, null, null, 1, null, null, DEFAULT)

I was now able to login again.
I know that the rest of the entries I deleted also had null slugs so I created entries in elements_sites for all the others I deleted. There were thousands. It would have been nice if I was an sql maestro but the best I could do was export an CSV of the results of my initial missing elements query, and then looped through the csv while creating an entry for each:
// Loop through CSV
$file = fopen("elements.csv","r");

while (($data = fgetcsv($file)) !== FALSE)
{
    // create query
    $id = $data[0];

    // INSERT (table name, column values)
    $insert = Craft::$app->db->createCommand()->insert('elements_sites', [
        'id' => $id,
        'elementId' => $id,
        'siteId' => 1,
        'slug' => null,
        'uri' => null,
        'enabled' => 1,
        'dateCreated' => '2021-04-03 04:19:48',
        'dateUpdated' => '2021-04-03 04:19:48',
    ])->execute();

}

Happy to say the site is now back at 100% health and I've made a backup of the db.
As a side note, it was pretty disappointing to learn that docker by default isn't backing up to Time Machine. I could have just restored the docker image but didn't realise there's these images aren't being backed up. A valuable lesson in making regular backups and checks along the way.


Eager Loading Users Returning "Array to String Conversion" Error I am trying to eager load users in a specific group to reduce queries. I've tried this:

                {% set designers = craft.users({
                    group: 'designers',
                    with: [
                            'userAgencyName',
                            'userAgencyUrl',
                            'userFreelancerAgency',
                            'userDescriptionServices',
                            'userBudget',
                            'userCity',
                            'userStateProvince'
                            ]
                }) %}

This consists of 5 user text fields and 2 user category fields. Although it's returning the array to string conversion error.

The loop is setup like this:

    {% paginate designers.limit(7) as designers %}

    {# Loop through Designers #}
    {% for designer in designers %}

{{ designer.userAgencyName }}

                {% for category in designer.userFreelancerAgency %}
                 {{ category }}
                {% endfor %}

                {% for category in designer.userBudget %}
                {% if category %}

                Budgets: {{ category }}

                {% endif %}
                {% endfor %}
                {% if designer.userCity | length %}

{{ designer.userCity }}, {{ designer.userStateProvince }}

                {% endif %}

{% if designer.userDescriptionServices %}{{ designer.userDescriptionServices }}{% endif %}

   {% endfor %}

Thanks in advance for any help you can give!

Just checked eager-loading a text field in a template and by eager-loading it you are actually converting the field to an array and therefore unable to template it as usual. Eager-loading is generally only useful on fields like categories, assets, and matrixes.


Entries search query by 2 custom fields So I have a Entry type that has two custom fields on it. Both fields are integer fields. I'd like to make a query in PHP that gets the entries by two custom fields, both of which are integer values. Here is my code so far:

    $query = [
        'year' => $year,
        'quarter' => $quarter,
    ];
    $seasonBoxes = \craft\elements\Entry::find()
                 ->section('boxes')
                 ->search($query)
                 ->orderBy('dateCreated asc')
                 ->all();

Please note: $year is independent of the entry creation date so I can't use the date filters.

Fields in craft that are not element is query by something called element criteria model.
In twig you do:

{% set result = craft.entries({
       section: 'boxes'
       orderBy: 'dateCreated asc'
       year: year,
       quarter： quarter
}).all() %}

In php

 $query = [
        'year' => $year,
        'quarter' => $quarter,
    ];
 $seasonBoxesQueryObject = \craft\elements\Entry::find()
                 ->section('boxes')
                 ->orderBy('dateCreated asc');
 $seasonBoxesQueryObject->year = $query['year'];
 $seasonBoxesQueryObject->quarter = $query['quarter'];
 $seasonBoxes = $seasonBoxesQueryObject->all();


Secondary Template for Structure I created a Profile structure for my client's employees. He asked if I could generate an email signature for them from their Profile. I figured out a way to put all the signatures on one page using a

{% for entry in craft.entries.section('profiles') %}

loop on a single page.

However, is there a way to give each person their own page for an email signature? /PROFILE/email-signature that pulls content from the profile. I want this to update dynamically as he adds/removes employees.

How would I create a secondary template for the profiles for an email-signature?

It sounds like you need to create a dynamic route by going to Settings > Routes > "New Route".  Then you'd set your custom route to profiles/{slug}/email-signature and decide which template to serve when the url looks that way.

You can either serve the _entry template you're serving for /profiles/john-doe or create a new one. Depending on the situation, you may need to set the entry in the template like...

{% set person = craft.request.getSegment(2) %}
{% set entry = craft.entries.section('profiles').slug(person).first %}

...in the event Craft can't figure it out because you're on a separate template.  Grabbing segment 2 means you're grabbing john-doe from the URL, which will help Craft know which entry to find.

Here's more info on routing in the docs: https://craftcms.com/docs/routing#dynamic-routes


Problem with SUM on Matrix blocks I have some Matrix blocks where I need to sum one of the fields within, but I only want to sum it when another field within that block is or is not empty.
{% set reimbursementAmount = craft.matrixBlocks()
  .relatedTo(cat)
  .fieldId(9)
  .sum('field_item_reimbursementAmount')
  .specialCase(':empty:')
  %}

With this, I get an error:
Impossible to invoke a method ("specialCase") on a string variable ("101.00").
How do I sum the desired field, but only where another field (specialCase) is empty (or is not empty, as the case may be).

I haven't tested this, but I think .sum() will execute your query, so put it at the end:
{% set reimbursementAmount = craft.matrixBlocks()
  .relatedTo(cat)
  .fieldId(9)
  .specialCase(':empty:')
  .sum('field_item_reimbursementAmount')
%}


How to search a matrix block with a specific handle? I want to query a specific matrix block using text search which will search all the searchable fields in that particular block and give me output in the form of blocks that I can further process.

I tried this

 {% set MatrixBlocks = craft.matrixBlocks()
.type('metaData')
.search(query)
.all() %}

But when I dump each block, I am seeing so many fields and not fields only from the particuar block (metaData) that I want to query.

What is the correct query?

You need to specify the fieldId of the Matrix block you're searching through.

{% set MatrixBlocks = craft.matrixBlocks()
.fieldId(123)
.type('metaData')
.search(query)
.all() %}


Where to place a front-end 'entry form'? I'm trying to add an entry form outside CP (for users with proper permissions), using this example:

http://buildwithcraft.com/docs/templating/entry-form

but there's no mentioning of how/where to add a page/template that will house the form. One place I was able to place it is the actual template for the entry which is also used for viewing the entry, but that's not what I need. I need a separate URL pattern and separate template file. E.g.:

mysite.com/recipes/{slug}/edit

or

mysite.com/edit-recipes/{slug}

Any help is greatly appreciated!

You'd put it in your craft/templates folder at something like craft/templates/recipes/new.html.  Then you'd be able to load that from http://mysite.com/recipes/new.

There's a good templating overview in the docs here.


Sort products by category field value All of my products have a category field called stateCat. These state categories have a field called stateImportance. This is because some states are more important than others and I want to sort the products based on that stateImportance number. I have no idea how to do this.

This is what I've tried:

{% set products = craft.commerce.products.order('stateCat.stateImportance asc').type('coins').limit(null) %}

This doesn't seem to work, how can I accomplish this?

This doesn't work out of the box with Craft as the category field is a relation field.

However you should be able to use SuperSort plugin.

{% set products = craft.commerce.products.type('coins').limit(null) %}
{% set orderedProducts = products | supersort('sortAs', '{stateCat.first.stateImportance}' %}


Craft 2 -> 3 Upgrade Error Database Exception: SQLSTATE[42000]: Syntax error or access violation: 1091 Can't DROP 'n2-cr_matrixcontent_column1_locale_fk'; check that column/key exists

This is the error I am receiving when attempting to update the database for the new version of craft. I've checked for that specific table and confirmed that it doesn't exist. How do I prevent it from trying to drop it or otherwise fix this problem?

For reference to anyone else that might have this problem. Some of the tables in my database did not have foreign keys in the specific Craft format. This occurred when table changes were done manually without knowing about this extra detail.
Shout out to Brad Bell with Craft support for catching and fixing the problem.


How to send email from Craft 3 custom plugin? I have created custom plugin in Craft 3 and want send email to receiver or site email when user submits a form.

Edit: After the migration to Craft 3.1.x you should rather use this Code
/**
 * @param string                            $html
 * @param string                            $subject
 * @param array|string|\craft\elements\User $mail
 *
 * @return bool
 */
public function sendMail(string $html, string $subject, $mail): bool
{
    return Craft::$app
        ->getMailer()
        ->compose()
        ->setTo($mail)
        ->setSubject($subject)
        ->setHtmlBody($html)
        ->send();
}

Edit: this is my old answer, valid for Craft 3.0.x
This is my code to send emails in Craft 3. Let me know if you have any questions.
use craft\mail\Message;

/**
 * @param $html
 * @param $subject
 * @param null $mail
 * @param array $attachments
 * @return bool
 */
private function sendMail($html, $subject, $mail = null, array $attachments = array()): bool
{
    $settings = Craft::$app->systemSettings->getSettings('email');
    $message = new Message();

    $message->setFrom([$settings['fromEmail'] => $settings['fromName']]);
    $message->setTo($mail);
    $message->setSubject($subject);
    $message->setHtmlBody($html);
    if (!empty($attachments) && \is_array($attachments)) {

        foreach ($attachments as $fileId) {
            if ($file = Craft::$app->assets->getAssetById((int)$fileId)) {
                $message->attach($this->getFolderPath() . '/' . $file->filename, array(
                    'fileName' => $file->title . '.' . $file->getExtension()
                ));
            }
        }
    }

    return Craft::$app->mailer->send($message);
}


Element API and Shopify plugin Is there any way to translate this:

{% set shopify = craft.shopify.getProductById({ id: entry.shopifyProduct, fields: 'variants, id' }) %}

to the Element API?

I've tried this, but obviously it doesn't work:

return [
  'endpoints' => [
  'api.json' => [
  'elementType' => 'Entry',
  'criteria' => [
    'section' => product,
  ],
  'transformer' => function (EntryModel $entry) {
    $shopify = craft()->shopify->getProductById({id:$entry->shopifyProduct});

    return [
      'id' => $entry->id,
      'title' => $entry->title,
      'url' => $entry->url,
      'shopifyId' => $entry->$shopify
    ];
  },
]
 ]
];

There are some issues with your PHP syntax – I didn't test this (not sure how the data model returned by craft()->shopify->getProductById() looks, and you'll need to verify that $entry->shopifyProduct returns a Shopify product ID), but at least the syntax errors should be fixed:

return [
    'endpoints' => [
        'api.json' => [
            'elementType' => 'Entry',
            'criteria' => [
                'section' => 'product',
            ],
            'transformer' => function (EntryModel $entry) {
                $shopify = craft()->shopify->getProductById([ 'id' => $entry->shopifyProduct ]);
                return [
                    'id' => $entry->id,
                    'title' => $entry->title,
                    'url' => $entry->url,
                    'shopifyId' => $shopify ? $shopify->id : null,
                ];
            },
        ]
    ]
];


GraphQL: Prevent users seeing entries authored by other users How can we filter what entries are returned by a GraphQL query so that users cannot see entries authored by other people?

For example, Editors can access everything but Writers can only access their own entries.

You can do this using a custom module that adds an authorId condition to element queries, for graphql/api requests.

use Craft;
use craft\elements\db\EntryQuery;
use yii\base\Event;
use yii\web\ForbiddenHttpException;

// ...

// Is this a GraphQL request?
if (Craft::$app->request->getActionSegments() == ['graphql', 'api']) {
    Event::on(EntryQuery::class, EntryQuery::EVENT_BEFORE_PREPARE, function(Event $event) {
        // Get the current user
        $user = Craft::$app->user->identity;

        // If no one is logged in, return a 403 error
        if (!$user) {
            throw new ForbiddenHttpException();
        }

        // Only Editors are allowed to see everything
        if (!$user->isInGroup('editors')) {
            /** @var EntryQuery $query */
            $query = $event->sender;
            $query->subQuery->andWhere(['authorId' => $user->id]);
        }
    });
}

Note: Since the results will start changing for the same element query depending on who is logged in, you’ll also need to disable the enableGraphQlCaching config setting.


How do you not output table field if there are no values? I'm doing, what I think should work fine, however, I'm still getting a blank table output on the page if the table field is left unfilled when creating the entry. It's like the "if" check is being ignored for some reason. The table with data outputs as expected fine. What am I missing here? Gotta be something simple. Here's a link to the page in question: http://nightowlmusic.org/family/rotiron

{% if entry.discography | length %}

                Discography

            {% for row in entry.discography %}

                {{ row.releaseName }}
                {{ row.releaseYear }}

                    {% if row.purchaseLink %}Click here to purchase{% endif %}

            {% endfor %}

{% endif %}

When you define a table field, it comes with one row by default. I'm not sure why this is. You can remove this row by clicking on the - icon:

To filter out those rows in twig, try:

{% for row in entry.discography if row.releaseName %}


GraphQL private schema returning public schema scope I am setting up GraphQL on my Craft project, v3.3.16.3
I have a public schema exposing a public entry type, and a private schema exposing a private entry type.
When I switch between them in the GraphQL -> Explore panel, both return the results of the public schema.

See attached screens.

Any suggestions would be much appreciated! Thanks :-)

It turned out that MAMP Pro was stripping out the Authorization header, so every request was treated as a request to the public schema. The solution for MAMP Pro was to enable "Identical PHP version for all hosts (module mode)" in the PHP tab.

Thanks to Brandon Kelly from the Craft forum for pointing me in the right direction.


Craft 3 add Simple Map in entry through plugin I am trying to fill in lat/lng data in the Simple Map field of an entry through a plugin. All information from entry is saved except for Simple Map. Apparently I am doing something wrong there.

Here is my code:

$entry = new Entry(); // use craft\elements\Entry;
$entry->.... // set fields
...
$entry->setFieldValues([
    'otherFields' => $value,
     ...
    'mySimpleMapFieldName' => [
       'lat' => 52.27, //$location['lat'],
       'lng' => 0.51 //$location['lng'],
]);
Craft::$app->elements->saveElement($entry);

I think what you are running into is the getField() method on #147 of the MapService. What this does is return a model based on whether this is an existing record or a post request and if neither return an empty model.

if (
        // Is this a Post request and isnt there a console request AND is there a value
        !\Craft::$app->request->isConsoleRequest
        && \Craft::$app->request->isPost
        && $value
    ) {

        // Create a new map model with the $value param - creating a model that takes the $value into account
        $model = new Map($value);
    } else if ($record) {

        // Is there a record? Create a model that takes these record params into account
        $model = new Map($record->getAttributes());
    } else {

        // We havent got a post request.or a record. This is what is happening to your input.
        $model = new Map();
    }
EDIT---------------------------------------------
If you Edit $model = new Map(); TO $model = new Map($value); Your above code works fine.

I am not sure as to the inner workings of Simple Map - have only used the C2 version. The best way to fix this for the long term is probably to create an issue on SimpleMap's github page. My recommendation is to replace the above else{} method, with what i described below. Maybe there is some way to get around this that doesnt involve source edits - like i said i dont know Simple map inside out - i might just be missing something obvious. In case there isn't i would recommend fixing the MapService with something like the below:

else {

    Didnt meet the satisfied conditions. Is $value an array and does it exist?
    if(!$value || !is_array($value)){

        // Not happy with this input - create a blank map.
        $model = new Map();
    }

        We're happy with the sended value - it isnt a post request. Lets take the value into account
        $model = new Map($value);
    }

I ran the above code with your example and it ran just fine.

I think it goes without saying that it is a terrible idea to just edit just your MapService file with the above code as a permanent solution as that will give you instability/incompatibility problems. What i would recommend is editing the method temporarily to test if this solves your problem - just to make sure. If it does it's probably wise to open an issue. Either if it does or doesn't - probably smart to open a github issue to see what the devs themselves say.

P.S - your code example is missing one array brackets at the end - probably smart to edit that before pasting it back.

Hope i was able to help in someway :)


Automatic in-page navigation plugin? I'm writing some pretty huge articles consisting of multiple (80+) Matrix blocks of various types. They're so long they'd benefit from in-article navigation for skip-links.

WordPress has a plugin called autogen_menu which creates linked navigation from the header hierarchy in a post. You just put in a small snippet where you want the generated nav to go and it generates all the links (and presumably id's on the headers) itself. Has Craft got anything similar, I've not been able to find a plugin that does this?

Or, would this be better outside of Craft entirely and done as JS?

If I'm understanding you correctly, you want users when they visit your site to have a secondary menu that has links to various points in the article. That would actually be very easy to do in Craft. It's also possible for you to paginate a page, but that would be far more in-depth.

For skip links, you would need to run over the matrix twice. You will also need an anchor matrix block. It can either be a dedicated block for anchor tags, or a header block. You run over it the first time to create your menu:

{% for block in entry.articleMatrix.type('header') %}

{{ block.header }}

{% endfor %}

Then later when you are running over your article, you can check for block type and add the id as needed:

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

{{ block.header }}

{% endif %}

This is a really basic example. It uses Bob Olde Hampsink's slugify plugin (it uses Craft's built in slug method). It would be better if you could determine (maybe with a drop down field in your block) what level of heading the block is. I suggest you also cache each matrix loop for performance.


Is there any way of setting / forcing a default image transform for images inserted via rich text blocks? I have an image transform that is designed for images inserted into posts, and I'd like to make sure this is always applied to any image in a post. The problem I'm having is that for images inserted via Rich Text Fields, selecting a transform is optional, and the wrong transform may be selected.

Ideally I'd like to set a default transform so I can tell content editors that they can insert images directly into posts and don't need to do anything with the "Select image transform" option... is there any way of doing this, though? Any help or advice would be much appreciated!

I don't think it's possible natively, yet (as of 2.3). However, the ImageSmith plugin addresses this need by providing a 'bulk transform' Twig filter which detects images in HTML, applies a specified transform, and rewrites the HTML to reference the transformed images.


Why is a "Brute Force Protection" dialog appearing on login? How to remove? After successfully logging into admin I seem to be getting this message in a browser auth dialog:

Brute force protection, Please use these credentials: User = 'u' and Password is the answer to 1+1”

What's causing this and how do I disable it? Very annoying!

Thanks

That message definitely isn't coming from Craft natively.

My guess is either:

You've got a Craft plugin installed that's listening to onBeforeLogin and/or onLogin events and is performing some custom business logic
Your host has some library/extension/etc. installed globally that is affecting your Craft install.


How to install plugin without composer? For the last weeks I've tried installing composer, but without any luck. I've really tried aaa  looott, and how frustrating it is, it's just not working with SSLv3 for some strange reason.
This was the thread I opened: Unable to get composer running to install CraftCMS

So I had to give up, at least for now, to be able to use Composer and had to decide to switch to manually setup craft, which I just did. But now I'm having a problem installing plugins. The Plugin store isn't working and it probably uses composer in the back (?). I've found a question here about how to manually install plugins without the plugin store, but... it also uses composer. Which isn't working here.

Is there another way of installing plugins manually?

Alright. Guess the conclusion to my question is that with Craft 3 it isn't realisticly possible to use the plugin store without composer.

Luckily I finally found the problem composer had in connecting to packagist via ssl. Just in case other people have problems with composer too and are running ESET, this might help: unable-to-get-composer-running-to-install-craftcms


Do something on save of an entry if that entry is in a particular section, then I want to do some task.

I can't really find the event docs I need to do that. Everything I've come across has been for Craft 2.

Any steps for a hint?

Craft::$app->elements->on(Elements::EVENT_BEFORE_SAVE_ELEMENT, function(ElementEvent $e) {

    // Make sure it's an entry.
    if ($event->element instanceof \craft\elements\Entry) {
        $entry = $event->element;

        // Check if it's in the section you care about
        if ($entry->sectionId == 1) {
            // Do your custom logic
        }
    }
});


Craft Contact Form Not Picking Up HTML I'm using the craft contact form plugin and I am trying to format the sent email as html. I have added the following to the primary contact form plugin class:

public function init()
    {
        craft()->on('contactForm.onBeforeMessageCompile', function(Event $event) {
            $postedMessage = $event->params['postedMessage'];
            $event->messageFields = $postedMessage;

            $html = '';
            foreach ($event->messageFields as $field) {
                $html .= '<p>'.$field.'</p>';
            }

            $event->message = $html;
            $event->htmlMessage = $html;
        });
    }

Simply to format into paragraphs. The event is fired ok and the desired output is being created. However the plugin service does not seem to be picking up the the htmlMessage variable has been set.

Currently this sends the email as plain text showing the paragraphs in the text as per $event->message but even if I remove $event->message it still sends the default plain text message ignoring the html one has been set. Any ideas anyone?

Cheers

We just fixed this yesterday with Contact Form 1.8.1.


Get entries whose title has a keyword or related to a category's title I am trying to get entries that either their title has the keyword or their category field title. I am getting them from my plugin, not twig.
I tried like this:

$keywordCategory= Category::find()->title($keyword)->all();
$entries = Entry::find()->title($keyword)->relatedTo($keywordCategory)->all();

but it must be in the title and the category field. Is there a way to check using where and orWhere?

You would have to create the relatedTo condition manually first and then pass it in to the orWhere method. This is untested, but should get you on the right track.

Reference the _applyRelatedToParam() method in the ElementQuery class:
https://github.com/craftcms/cms/blob/3.1.26/src/elements/db/ElementQuery.php#L1724-L1727

$keywordCategory = Category::find()->title($keyword)->all();

$parser = new ElementRelationParamParser();
$relatedTo = $parser->parse($keywordCategory);

$entries = Entry::find()
    ->where(['title' => $keyword])
    ->orWhere($relatedTo)
    ->all();


Can I "circle crop" an image asset? Is it possible for me to create an image transformation that generates a cirle cropped thumbnail?

Just like this:

The short answer: No.
However, as this answer states, it will be possible to do this in the future.

Just as a tip, I know it doesn't answer your question: it's an effect you can easily achieve with CSS, by rounding the corners to 50%.


sendEmail messages not being received by Exchange server I've been able to get this to work with my gmail address but not my work's Exchange email account. How can I make this receivable by exchange mail servers?

    $email = new EmailModel();
    $email->toEmail = 'EMAILADDRESS';
    $email->subject = 'test';
    $email->body    = 'test';

    $sent = craft()->email->sendEmail($email);

I agree with Damon.  I use Exchange and haven't noticed any issues with receiving emails (either from Craft system or withing my own plugins).  I am using Mandrill to send them.  You might have greater success if you fill out more of the model (fromEmail etc) but more than likely it's using php mail that is the core issue.

Email deliverability is these days a complex thing, much better to leave it to the experts, although for best results even then you still need to pay attention to your Mandrill & domain setups (SPF/DKIM etc).


Get asset folder and filename together I am using a 3rd party service to run the image processing so I do not need full URL's for the images. I just need it to spit out the relative path name of the asset, not the absolute URL. I seem to be able to get either the asset.folder or the asset.filename but not both.

{% if entry.homepageImage|length %}
{% set asset = entry.homepageImage.first() %}
  <img ix-path="{{ asset.filename }}" alt="Test Image">
{% endif %}

I did try including the folder when setting the asset but that didn't work either, plus seems quite convoluted for something relatively simple.

{% set asset = entry.homepageImage.folderId(2).first() %}

AssetFileModel's getPath should do what you're looking for.

<img ix-path="{{ asset.getPath() }}" alt="Test Image">


Filter based Search Form Previously on EE I've used Low Search to generate a filter based search form, based on categories. But with Craft I can't seem to find an add-on - Or even know if I need one!

What I'm trying to achieve is a filer menu with categories e.g.:

[ ] Category 1
[x] Category 2
[ ] Category 3
[x] Category 4
   [ ] Category 4.1
   [ ] Category 4.2
[ ] Category 5

I've been reading over the documentation over at:

https://craftcms.com/docs/searching and https://craftcms.com/docs/templating/search-form

But I'm struggling to see how I can make this work within a search form itself.

I'm thinking I can generate a query fine to search the categories. But I can't work out how to link what is checked with a query.

Any help would be gooooood :)

I managed to figure this out by looking through a few other posts:

Advanced Search
Building a simple search by multiple categories
Building Results From Advanced Search Form
How to filter entries by clicking multiple categories on front end
Fetching entries from an advanced search form on the front end

Which I then took their knowledge and put together my own form and results template. With the results I wanted the same code & template to be used for search results AND the general "knowledge" page.

Filter Form

<form action="{{ url('knowledge') }}">

        {% set categoryEntries = craft.entries.limit(null) %}

        {% for category in craft.categories.group('knowledge') %}

            {% set categoriesEntryCount = categoryEntries.relatedTo(category).total() %}

              <input type="checkbox" name="category[]" value="{{ category.slug }}" id="{{ category.slug }}">
              {{ category.title }} ({{ categoriesEntryCount }})

        {% endfor %}

</form>

Results

    {% set parameters =
        {
            section: 'channelKnowledge',
            limit: '1'
        }
    %}

    {% set categoryQuery = craft.request.getParam('category') %}

    {% if categoryQuery %}
        {% set categoryQueryCategories = craft.categories.group('knowledge').slug(categoryQuery) %}
        {% set entries = craft.entries(parameters).relatedTo(categoryQueryCategories).order('score') %}
    {% else %}
        {% set entries = craft.entries(parameters) %}
    {% endif %}

    {% paginate entries as channelKnowledgeEntries %}

    {% if entries|length %}

        {% for entry in channelKnowledgeEntries %}

            {{ entry.title }}

        {% endfor %}

    {% else %}

No Results

    {% endif %}

    {% if paginate %}

            {% if paginate.prevUrl %}

                    Previous

            {% endif %}

                {% for page, url in paginate.getPrevUrls(5) %}

                        {{ page }}

                {% endfor %}

                        {{ paginate.currentPage }}

                {% for page, url in paginate.getNextUrls(5) %}

                        {{ page }}

                {% endfor %}

            {% if paginate.nextUrl %}

                    Next

            {% endif %}

    {% endif %}

{% endpaginate %}


Localization Section propagation settings, and related entry field setting "Manage relations on a per-site basis" Craft 3.4.20.
Site is running multiple localizations
Sections:
Blog Post
Propagation method set to, "Save entries to all sites enabled for this section"
Blog Category (Structure entry with nothing more than the default Title)
Blog Post Section entry has a field to relate to our Blog Category Structure. We have a field under our Blog Posts entry with the option, "Manage relations on a per-site basis".

A Blog Post entry has an entry field to where you can select multiple Blog Category entries from a Structure.
Issue is that editors publish Blog Posts and may not consider the other locales. You would think the relationship field would take into consideration of the setting, Manage relations on a per-site basis.
When publishing an entry under the Default site (in our case North America), and the publishing editor disregards the other Locales (the toggle drop-down for an entry on publish view), the field data of the entry relationship for "Blog Category" on North America duplicates itself to the Europe relationship field.
I don't know if this is intentional, or if the Manage relations on a per-site basis setting is not being factored in?
Is there a way to exclude certain fields from being populated with the same localization data as the default entry. I simply thought the field settings, Manage relations on a per-site basis would be factored into this and be left null when publishing a North America entry, but Europe, and all the other sites receive that same field relationship value based on North America Blog Post publish. It seems as though there is no way to exclude certain fields from doing this, and is there a solution to this?
Is it intended for the Section settings Save entries to all sites enabled for this section to override this field setting with first publish?

This is intended behavior – when you first create a new entry, any content you enter will be copied to other sites, up until the point where you either save the entry, or start editing one of the other sites.
If you’re worried about unintended content getting published in other locales, then I’d suggest you set the other sites’ default statuses to disabled, from your section’s settings. Once Craft 3.5 comes out you’ll have another option as well: sections have a new propagation method option which gives entries control over which sites they should be saved to, so the entry won’t exist at all in other sites up until someone explicitly enables the site for the entry.


How can I limit the output of assets randomly if an asset exists? How can I limit the output of assets based on this criteria?

search all entries randomly in section "homes" for only entries with at least one asset image
limit those results to 8 random assets

I tried this but it does not always show exactly 8 asset images as the random is called first:

{% set assets = craft.assets.limit(null) %}

{% for homesEntry in craft.entries.section('homes').limit(8).order('RAND()') %}
    {% if homesEntry.homeImages|length %}
        {% set asset = homesEntry.homeImages.first() %}

        {% if asset %}

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

Any help is appreciated.

This is how you do it in case anyone is looking for this.

{% set assets = craft.assets.limit(null) %}

{% set randomEntry = craft.entries.section('homes').order('RAND()').relatedTo({
    targetElement: assets,
    field: 'homeImages'
}) %}

{% for homesEntry in randomEntry.limit(6) %}
    {% set asset = homesEntry.homeImages.first() %}

    {% if asset %}

    {% endif %}
{% endfor %}


Plugin for creating categories on an entry page in Control Panel Is there a plugin that allows to add a category via an entry page? I like how you're able to add categories in Wordpress admin right on a post page, not only via Categories section — this seems to facilitate the categorization of content by editors. It's possible that they'd rather skip the Assign a category button than do some extra work to create the required categories, and ability to enter new categories within the entry page would help to avoid that.

Can you use tags maybe? I think they work kind of the same, and u're able to add new ones right in the entry.