How do I create a custom Twig extension which includes third party code? I found several solutions to build a dynamic, complex navigation in craft. One is described here:
 Adding active class to globally cached navigation. Now i would like to create a more powerfull twig filter for
 creating different navigation and breadcrumb types with selecting of active links. I already wrote some test code in plain php and used for this the library simplehtmldom (helper for changing dom elements in php like in jquery). A demonstration about what i want to do can be found here:
 http://www.bahu.ch/craft/. Now i started with creating the twig filter, but i can't include the library in my plugin. Here is a quick overview of my plugin code.

   <?php
   namespace Craft;
   use Twig_Extension;

   use Twig_Filter_Method;

Now i need to include the library (i know, that the next line is incorrect)

   include('simple_html_dom.php');

   class k4NavigationTwigExtension extends \Twig_Extension

   {

public function getName()
{
    return 'k4Navigation';
}

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

public function k4Navigation($navigation)
{

    $html = str_get_html($navigation);

on the next line the current url should replace the string "test.html"

    $selectElem = $html->find('a[href="test.html"]')[0];

    if (is_object($selectElem)){
       // loop li and set class active
        for ($i = 1; $i <= 20; $i++) {
            $selectElem->setAttribute("class","active");
            $selectElem =  $selectElem->parent();
            if (!is_object($selectElem)){
                break;
            }
        }
    }

    return $html;

   }

   }

Maybe someone can give me a hint, how to includ the library and the first example? You can download the full test code and started plugin from here: https://github.com/tombauer/k4-navigation

Many thanks for any help!

Sunny regards
Tom

Douglas McDonald's answer is correct with one issue though. The import statement is actually case sensitive

  Craft::import('plugins.myplugin.twigextensions.MyTwigExtension');

I also have 2 additional notes:

The getName() method is deprecated so you shouldn't bother with it
The getFilters() method can be written much shorter, for example:

public function getFilters()
{
    return [
        'myfilter' => new \Twig_Filter_Method($this, 'myfilter'),
    ];
}


Will having large numbers of Fields decrease site performance? I know that on page load Craft makes multiple queries to get Fields. I have about 300 separate fields on a pretty large site. I know it's probably better to reuse fields when I can, but in many cases I can't rename fields or field instructions so I wouldn't be able to name them semantically for the user.

Is it OK to have this many fields on my site, or should I find another strategy to manage my large number of fields, many of which are very similar?

I can't answer your question directly as I never got even close to 300 fields yet. But even with 50 fields I had some serious slowdowns, especially when getting related entries in form of assets and such.

I think you should definitely consider using the built in cache function to get good performance.

In regards to that field name / instructions problem you ran into, I can tell you that this is something I hope that gets changed in the future. I already made @Brandon Kelly aware of this problem and he probably has it on "the list".

.

Edit:

After thinking a bit more about this, I'd go with @Simon Kuran and believe that the number of fields have rather negligible moderate impact on your overall performance.

It's more about the numbers of DB queries and not that much about the amount of data they request.
Be careful with building and inquiring relationships in particular, as they can lead to many (unintentional) DB calls. But first and foremost: use caching. The {% cache %} tag is there for a reason! ;)


How can I filter selected/related entries by their categories? I have a section called "Events" and an Entries field, we'll call myEntriesField to select related entries from another channel called "Exhibitors"

On the Events page, I need to display the related Exhibitors grouped by their categories. And if there are no related Exhibitors in said Event, I need to hide the surrounding html that displays the category title etc.

I have this in my template:

        {% set theListings = entry.myEntriesField %}

        {% set thisCategory =
             theListings.relatedTo(craft.categories.slug('the-category-i-need'))
        %}

        {% if thisCategory | length %}

Category Title

            {% for theEntry in thisCategory %}

{{ theEntry.title }}

                    ...more entry data stuff...

            {% endfor %}

        {% endif %}

        {% set thisOtherCategory =
             theListings.relatedTo(craft.categories.slug('the-next-category-i-need'))
        %}

        {% if thisOtherCategory | length %}

Category Title

            {% for otherEntry in thisOtherCategory %}

{{ otherEntry.title }}

                    ...more entry data stuff...

            {% endfor %}

        {% endif %}

But this displaying ALL Exhibitors, grouped by their categories, rather than just the related Exhibitors selected in the Event entry.

Any ideas what I am missing here?

Start by looping thru each category. Say, all categories in a category group called "eventsCategories." Then find entries related to each category (if any).

{# loop through each of the categories #}
{% for category in craft.categories.group('eventsCategories') %}

  {# find the exhibitor entries that are related to both the Event entry and category #}
  {% set categoryListings = craft.entries({
    section: 'exhibitors',
    relatedTo: ['and',
      { sourceElement: entry, field: 'myEntriesField' },
      { targetElement: category, field: 'myCategoriesField' }
    ]
  }) %}

  {# Only show this category if there were any related exhibitors #}
  {% if categoryListings|length %}

{{ category.title }}

    {% for listing in categoryListings %}

{{ listing.title}}

    {% endfor %}

  {% endif %}
{% endfor %}


Show all entries from an entry field I have an Entry field (page) as part of my Matrix field (footer).

When the client selects 5 entries, I want to display them all in my list and not just the first. I can only seem to get my code working with .first or .last. Everything else I try gives me the old "Object of class Craft\ElementCriteriaModel could not be converted to string" error.

{{ block.navSection }}

        {% if block.type == "footerCategory" %}
        {% set page = block.page.first() %}

{{ page.title }}

        {% endif %}

My matrix for this list:

The elementCriteriaModel is a class/object that handles your search. It's a class that combines multiple methods to fetch entries from your database with an iterable interface on it.

That means: when you receive an entry you get all the queries you need attached to it to pull all the relationship instead of loading all the other entries all the time. So entry.matrix is nothing but database command to pull the other entries which makes craft fast. Otherwise you would take much more time.

To make it short: when you loop through your elementCriteriaModel the method .find() is executed, that fetches all your entries and return them as an array. The method first() returns only the first element, last() returns only the last element.

In order to pull all you just need to loop block.page
{% for entry in block.page %} will to it


Action route not available from URL. What do I have wrong? I built a plugin for Craft 3 and need to run one of its actions via CRON. I know I can set this up as a console command, and will do that, but before I get there, I'd like to solve this issue.

I noticed my CRON was failing, and when I attempted to run the URL myself, at http://campaigns.gcx.loc/actions/gcxCampaignTools/stats/syncCampaignsRemote, I got this error:

yii\base\InvalidRouteException: Unable to resolve the request "gcxCampaignTools/stats/syncCampaignsLocal". in /Users/Chad/Sites/gcx-campaigns/vendor/yiisoft/yii2/base/Module.php:537
Stack trace:
#0 /Users/Chad/Sites/gcx-campaigns/vendor/craftcms/cms/src/web/Application.php(299): yii\base\Module->runAction('gcxCampaignTool...', Array)
#1 /Users/Chad/Sites/gcx-campaigns/vendor/craftcms/cms/src/web/Application.php(566): craft\web\Application->runAction('gcxCampaignTool...', Array)
#2 /Users/Chad/Sites/gcx-campaigns/vendor/craftcms/cms/src/web/Application.php(278): craft\web\Application->_processActionRequest(Object(craft\web\Request))
#3 /Users/Chad/Sites/gcx-campaigns/vendor/yiisoft/yii2/base/Application.php(386): craft\web\Application->handleRequest(Object(craft\web\Request))
#4 /Users/Chad/Sites/gcx-campaigns/public_html/index.php(21): yii\base\Application->run()
#5 {main}

Next yii\web\NotFoundHttpException: Page not found. in /Users/Chad/Sites/gcx-campaigns/vendor/craftcms/cms/src/web/Application.php:570
Stack trace:
#0 /Users/Chad/Sites/gcx-campaigns/vendor/craftcms/cms/src/web/Application.php(278): craft\web\Application->_processActionRequest(Object(craft\web\Request))
#1 /Users/Chad/Sites/gcx-campaigns/vendor/yiisoft/yii2/base/Application.php(386): craft\web\Application->handleRequest(Object(craft\web\Request))
#2 /Users/Chad/Sites/gcx-campaigns/public_html/index.php(21): yii\base\Application->run()
#3 {main}

The action works from a front end link with the following code when I am logged in (user must be logged in to use the entire app, so login is required to run the action as well):

Sync Campaigns

Because it worked when logged in, I thought I may need to allow anonymous in the controller, but that was already in place. I tried both protected $allowAnonymous = true; and protected $allowAnonymous = ['actionSyncCampaignsRemote']; with the same results.

Here is a screenshot of my plugin file structure and controller actions: screenshot

As you can see there I did put URL: /actions/gcx-campaign-tools/stats/sync-campaigns-remote in the code comments when I built this. Loading that URL produces the same error.

What am I missing here?

Turns out the controller action was running, but since I was just using return, Craft was looking for a template to show once the functions were complete, and failing when it didn't find one. Using die(); after the function runs is working fine.


Linking to Sections: do it or do something different? I'm pretty new to Craft, so I'd like to know if there's a best practice when linking to a section, assuming the section has an index.html template for its "homepage."

I'm currently using the following to loop through all Sections and then give me their URL, but in sort of a hacky way. This is one of a couple ways I've found to do this, but my Homepage singlepage entry outputs as http://example.com/__home__ which is super weird.

{% set sections = craft.sections.getAllSections() %}

{% for section in sections %}

        {{ section }}

{% endfor %}

```

If the best practice is to do something completely different, then feel free to set me straight! Thanks!

I've found what is probably a better solution;

I create a Single section for each Channel/Structure and use that as a directory for that channel/structure. I then loop through all sections and see if they're of the single type, then get the first (and only) entry of that section.

{# Get all Section #}
{% set sections = craft.sections.getAllSections() %}

{# Loop through all single sections #}
{% for singleSection in sections if singleSection.type == 'single' %}

    {# Get the first (and only) entry of that section #}
    {% set singleEntry = craft.entries.sectionId(singleSection.id).first %}

    {# Output #}

        {{ singleSection }}

{% endfor %}

Let me know if you guys have a better way of doing this!


Setting Charge Webhook in config file How do I set the webhook URL for Charge in the config file?

I've got my /config/charge.php created.

Figured it out:

<?php

return [
    'webhook' => 'http://example.com',
];


Removing /index.php/ from url breaks site When I try the solution mentioned here, my site breaks, pages not found. Even the /admin/ pages break, losing all styling. The only page which loads is the homepage.

Any thoughts about why? I was having htaccess issues, but I believe those are all fixed now.

This is the htaccess file in the the top level craft folder

<IfModule mod_rewrite.c>
    RewriteEngine On

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

There is the root:
brianfeeney.us/

Which contains both:
brianfeeney.us/blog (WP)
brianfeeney.us/craft

The index.php in my root points towards /blog/

thanks for the help

I hope you figured it out however, I just found adding

RewriteBase /

right under RewriteEngine On fixed my issue.


Custom Field Settings: Unknown Property Error I have a custom field with a setting for regionType, but when I try to save the field I get this error:

  Setting unknown property:
  kgrote\siteutilities\fields\Regionselect::regionType

In my fieldtype file I have this to load the settings field:

public function getSettingsHtml()
{
    // Render the settings template
    return Craft::$app->getView()->renderTemplate(
        'site-utilities/_components/fields/Regionselect_settings',
        [
            'field' => $this,
            'settings' => $this->getSettings()
        ]
    );
}

And the settings template looks like this:

{% import "_includes/forms" as forms %}

{% set input %}
    {{ forms.select({
        id: 'regionType',
        name: 'regionType',
        options: ({
            'usStates' : 'US States & Canadian Provinces',
            'countries' : 'Countries'
        })
    }) }}
{% endset %}

{{ forms.field(
    {
        label: "Region Type"|t('app')
    },
    input
) }}

My field is a simple pre-filled dropdown, so I'm importing most of the methods for my field from craft/vendor/craftcms/cms/src/fields/BaseOptionsField.php.

I don't see much in the source code that relates to settings, so I'm not really sure what's causing this error.

The name of your select is regionType thus it will try to store the property regionType in your field. When you call the field value it will set the property value in you class.

You either need to include the property or change it to an existing one.


Remove username from photoUrl path I just realized that Craft puts the username into the path of the photoUrl. Since I use email addresses as usernames, I don’t think it’s a good idea to expose the email addresses of all users on the web.

Question: Is there a way to remove the username (in my case email address) from the photo path and replace it with the users ID for example?

I would like to get around adding a new asset field for every user, since the user photo would be fine.

Bonus question: is there any way to protect user photos from access at all? It looks to me like the urls to the user photos could be guessed quite easily.

Best, Mark

Since I use email addresses as usernames, I don’t think it’s a good idea to expose the email addresses of all users on the web.

I agree, and that's something we overlooked when we added the 'useEmailAsUsername' config setting.

  Question: Is there a way to remove the username (in my case email address) from the photo path and replace it with the users ID for example?

Currently not, unfortunately.  And it's hard-coded so there really isn't a chance for a plugin to override the behavior.  And I don't think it's really any better to be displaying a user's ID or UID as well, since people wouldn't expect those to be publicly available by default.

  Bonus question: is there any way to protect user photos from access at all? It looks to me like the urls to the user photos could be guessed quite easily.

Again, no.

I think the proper solution to both problems would be, upon uploading a user profile photo, generate a random string and save that along with the user in the database.  The string would be used in the URL when retrieving the user's profile photo.

I'll add it to our list to address.


Return specific Matrix row? I'm looking to be able to return the info from a field(s) from a Matrix row where I know which row I want (long story). I had a guess at various ways of doing this, but in the end the only way that worked was to run the loop with an if statement to limit the output to a given row's id, e.g:

{% for block in entry.bodyRepeater %}
    {% if loop.index==2 %}
    <h3>{{ block.heading }}</h3>
    {% endif %}
{% endfor %}

Guessing there might be a better way though?

This works but using this code can be a problem if you are dealing with a huge number of rows.

To access the n-th row, you can use:

{{ entry.blockRepeater.findElementAtOffset(n-1).heading }}

I found this method in the ElementCriteriaModel class. You can test if a certain row exists using entry.blockRepeater.offsetExists(n).


Reuse items from array with forloop I have a loop of a list of regions on a project, this could be an infinite list of areas as my client's customer-base grows.

The project branding has four key colours, I have these in an array:

{% set themes = [
    'yellow',
    'red',
    'teal',
    'blue'
] %}

What I'm looking to do is grab one of these themes as I loop over my regions with a basic {% for region in regions %}, then on the 5th, 9th and so on loop jump back to #1.

Do you mean to have it just assign them one after the other? If so, then you can just use Twig’s cycle function.

{% set themes = [
    'yellow',
    'red',
    'teal',
    'blue'
] %}

{% for region in regions %}
 {{ region.title }}
{% endfor %}


How to limit number of entries to a given user/user group I have a site where users can add entries of an entry type/section called Listings.

I would like to limit the number of Listings to a maximum of three per user.

In another CMS I did this by writing a plugin that got triggered when a new Entry was created. This plugin determined the number of existing Entries for a given user and if the maximum was reached, the plugin cancelled the creation of a new entry and instead showed a message that the user had reached their maximum limit of entries.

Not to say that this is the best way to do it, or do it in Craft, but I am new to Craft CMS and have been looking for a hook or event that is triggered when a new entry is created, but I don't seem to be able to find anything like that.

I have also done a fair bit of searching on this topic and cant seem to find any Stack questions or posts on the net....

Any suggestions much appreciated.....

You might want to take a look at this

Your condition will be

$author = Craft::$app->getUsers()->getIdentity();
$numberOfEntriesByUser = Entry::find()->sectionId($entry->getSection()->id)->authorId($author->id)->count();
if($numberOfEntriesByUser){
    $event->isValid = false
}

You should make sure the author is not an admin or Craft::$app->getRequest()->getIsCpRequest() is false otherwise you won't be able to save new entries as well.

Keep in mind to check for a current user as well. There won't be a user for cronjobs / other public post request


Looking for comment plugin I know that it is possible to let user comment entries using the guest entries plugin or to implement a third-party solution.

But I wonder if is someone working on a dedicated comment plugin?

Don't know of any comment plugins yet but the easiest thing to do is to Integrate Disqus. You just drop the embed code in and paste in your entry ID.


Image Transforms: Is there a way to detect portrait or landscape? I'm looking to setup an image transform via the control panel but I only want to resize the image (scale - not crop or fit). The trouble is that I don't know whether the uploaded image will be a portrait or a landscape. Is there a way to set it to just scale to a maximum bounding box?

For example, if I want images to be a maximum 1000px width or height (whichever the longer edge is), how can I set that and maintain aspect ratio?

The best way would be to use the Fit image transform.

Set the transform to 'Fit' and set both your width and height values to 1000px. That way the image will continue to scale until the first longest edge reaches 1000px.


ActiveRecord defineAttributes() I have just started to build my first plugin with Craft CMS.

Im at the part where I want to defne my database table.

http://buildwithcraft.com/docs/plugins/database

For the method definedAttributes() what values will the array accept.

It looks like I can define values and types, but how do i add field lengths, primarykeys etc..

Are there some other docs that I can look at?

Thanks for your help.

You best bet would be to start by knowing all the exisiting default attribute types in this file:

craft/app/enums/AttributeType.php

Then look in

craft/app/helpers/ModelHelper.php
and
craft/app/helpers/DbHelper.php

There you will find all sorts of properties for column types and their default configs options like maxLength. Here is all the ColumnTypes defaults:

public static $attributeTypeDefaults = array(
    AttributeType::Mixed      => array('model' => null, 'column' => ColumnType::Text),
    AttributeType::Bool       => array('maxLength' => 1, 'default' => false, 'required' => true, 'column' => ColumnType::TinyInt, 'unsigned' => true),
    AttributeType::ClassName  => array('maxLength' => 150, 'column' => ColumnType::Varchar),
    AttributeType::DateTime   => array('column' => ColumnType::DateTime),
    AttributeType::Email      => array('minLength' => 5, 'column' => ColumnType::Varchar),
    AttributeType::Enum       => array('values' => array(), 'column' => ColumnType::Enum),
    AttributeType::Handle     => array('maxLength' => 255, 'reservedWords' => 'id,dateCreated,dateUpdated,uid,title', 'column' => ColumnType::Varchar),
    AttributeType::Locale     => array('column' => ColumnType::Locale),
    AttributeType::Name       => array('maxLength' => 255, 'column' => ColumnType::Varchar),
    AttributeType::Number     => array('min' => null, 'max' => null, 'decimals' => 0),
    AttributeType::SortOrder  => array('column' => ColumnType::TinyInt),
    AttributeType::Template   => array('maxLength' => 500, 'column' => ColumnType::Varchar),
    AttributeType::Url        => array('maxLength' => 255, 'column' => ColumnType::Varchar),
);

You will also see in the DbHelper.php how the column types map into the mysql definition of the table like so:

case ColumnType::Decimal:
            {
                $def = 'DECIMAL('.$config['length'].','.$config['decimals'].')';
                break;
            }

Hope that helps. I would encourage you to look at all the defineAttributes() methods in the craft/app/records directory.


Does Craft have built-in queue handling for outbound mail? Does Craft have built-in queue handling for outbound mail? For example if Settings -> Email -> Protocol is set to "SMTP" and the mail server is temporarily down when an email is to be delivered, the email will then be delivered later when the mail server is online again?

I guess the answer is no, and that it's better to use sendmail if it's important messages?

I guess the answer is no

Correct... Craft is just the middle-man between creating the email and using whatever selected service is used to send it.


Custom event not sending notification email I'm creating a plugin called "Membership" to handle user subscriptions through Stripe. I want to use SproutEmail to handle notification.

I've created a custom event as per the Sprout instructions:

<?php
namespace Craft;

class SproutEmail_SubscribeEvent extends SproutEmailBaseEvent
{
    /**
     * Returns the qualified event name to use when registering with craft()->on
     *
     * @return string
     */
    public function getName()
    {
        return 'membership.onSubscribe';
    }

    /**
     * Returns the event title to use when displaying a label or similar use case
     *
     * @return string
     */
    public function getTitle()
    {
        return Craft::t('When a user subscribes to a membership plan.');
    }

    /**
     * Returns a short description of this event
     *
     * @return string
     */
    public function getDescription()
    {
        return Craft::t('Triggers after a user has subscribed.');
    }

    /**
     * Returns the data passed in by the triggered event
     *
     * @param Event $event
     *
     * @return mixed
     */
    public function prepareParams(Event $event)
    {
        return [
            'value' => $event->params['user']
        ];
    }
}

SproutEmail is picking this up and I can select it as a rule:

I added a listener to my plugin for membership.onSubscribe to ensure it's working properly:

craft()->on('membership.onSubscribe', function(Event $event) {
    MembershipPlugin::log('membership.onSubscribe was triggered.');
});

And it appears to be:

2017/02/16 15:07:33 [info] [plugin] membership.onSubscribe was triggered.
in /home/vagrant/Code/sbl.loc/craft/app/etc/plugins/BasePlugin.php (65)
in /home/vagrant/Code/sbl.loc/craft/plugins/membership/MembershipPlugin.php (56)
in /home/vagrant/Code/sbl.loc/craft/plugins/membership/services/MembershipService.php (15)

******************************************************************************************************

However SproutEmail doesn't sent out any notification email and when I check the logs for the plugin there is no mention that my custom event was triggered.

Does anyone have any idea what the issue might be?

We got to the bottom of this issue and it turned out to be that the SproutEmail_SubscribeEvent::validateOptions() method was returning false. Updating this to ensure the options were being validated properly fixed the issue:

public function validateOptions()
{
  return true;
}

We've updated the docs and will also more clearly document this in the SproutEmailBaseEvent class in the next release.


Live Preview not loading - https / http conflict My live preview isn't loading. I'm getting the following error:

Mixed Content: The page at 'https://www.site.com/admin/entries/pages/611-title' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://www.site.com/path/title?token=lxDnfeMzRFOM-xI2IylUQZ2r1XkiQlgR'. This request has been blocked; the content must be served over HTTPS

I'm not sure where the http request is coming from though. My env file sets the site url using https, and the Base URL in settings > sites also uses https. Is there another location where Craft could be getting the http from?

UPDATE: I tweaked my htaccess settings, and now I'm getting a different error:
[Error] Failed to load resource: the server responded with a status of 500 () (page-title, line 0) https://www.example.com/path/page-title?token=zVyQLpLN9K8fZ9FJKYf6Y6l9gEvHAWts
If I try to access the url in the error, I get a HTTP 400 – Bad Request – yii\web\BadRequestHttpException error

I had the same issue!

In my case, it was because I had defined http://example.com as my siteUrl for the production environment, in my general.php config file. Simply changing this to https://example.com fixed it!

Sample code: (Change 'production' to match the env you are targeting of course)

'production' => [
    // Base site URL (if multisite)
    'siteUrl' => [
        'mysite!' => 'https://example.ca',
    ],
    //OR Base site URL (if single site)
    'siteUrl' => 'https://example.ca'
],

More on the general.php config file: https://docs.craftcms.com/v3/config/config-settings.html


Can I eager load data within a template? I have a Matrix field with a single block type and within that, a number of fields that I need to pull out:

{% for roomContent in hotelEntry.roomsAvailable %}
    {% if roomContent.code == room.roomTypeCode %}

room code = {{ roomContent.code }}

            description = {{ roomContent.description }}

            {% for image in roomContent.images %}

            {% endfor %}

    {% endif %}
{% endfor %}

I am doing this on a listing page where there are around 60 entries, so this is resulting in a lot of calls to the DB.

Is there a way I can eager load all of the data for all of the entries outside of this loop so I'm not recursively calling for data?

No you can't with any build in Craft functions. I've added a feature request for this on Crafts feedback site.

What you can do for now is to use Mike Peppers excellent Plugin "Fetch" which pre-fetch relations for you.

Ser here https://github.com/mdcpepper/fetch


Change base URL for email activation link? I am using Craft as a headless CMS and have set base Url/siteUrl to the url of my React/Gatsby site.

I needed to do this as my navigation plugin, Navie, appends it by default.

But now when users registers, they are sent an activation email with the Gatsby url.

How can I change this?

Thanks

You can use a Twig replace filter in the email template to replace the URL with whatever you like. (I'm using this method myself because we have a similar problem on multi-site installs). To do this you'll need to be using custom templates for all system emails: Settings > Email > HTML Email Template

I'd set that to something like emails/index, which could then be like this, routing out to separate template files depending on the emailKey:

{# Craft has four predefined email keys:

    account_activation
    verify_new_email
    forgot_password
    test_email

... route to them here, or fallback to default
#}

{% include [
    'emails/' ~ emailKey ?? null,
    'emails/default'
] %}

Then emails/account_activation.twig could be something like this using the replace filter on the link variable:

{% extends 'emails/_emailLayout' %}

{% set lockscreenText = 'Activate your account' %}

{%- set heading -%}
    Hi {{ user.friendlyName ?? 'there' }},
{%- endset -%}

{% block content %}

Your account is now set up and ready to use, with your email address as your username.

To activate your account, click the following link:

{% endblock %}

{% if link is not defined %}
    {% set link = 'http://local.test' %}
{% endif %}
{% set buttonLink = link|replace('https://old.com/actions','https://new.com/actions') %}
{% set buttonText = 'Activate your account' %}

...while emails/_emailLayout would have all the complicated mess of HTML that cross-client email requires.


What can we do to help avoid member activation emails going to spam? We have a new Craft site that includes front-end member registration. We've heard from the client that many of the activation emails are getting stuck in spam filters (and I just tested with the same result). Is there anything that we can do to avoid this? Perhaps add SPF records?

This the best article I've read on reliably delivering emails through code: http://blog.codinghorror.com/so-youd-like-to-send-some-email-through-code/


Search Plus - How to skip an entry in mapping? With the Search Plus plugin, it's possible to define a custom mapping of your Entries for your Algolia index. This is basically a two-part process:

Call the searchPlus_addAlgoliaMapping to declare which function controls the mapping.
Write the function which controls the mapping.

I've done both of these, and it's working very well. Here's an example of my mapping function...

return [
    'objectID' => $entry->id,
    'uri'      => $entry->uri,
    'title'    => $entry->title,
];

However, there are certain entries which should be excluded from the search index. My instinct tells me to simply wrap a conditional around that mapping, and return false (or null) for entries which should be excluded...

if ($entry->includeInSearch) {
    return [
        'objectID' => $entry->id,
        'uri'      => $entry->uri,
        'title'    => $entry->title,
    ];
} else {
    return false;
}

The problem is, this seems to cause an error when Search Plus tries to export to Algolia...

Which leads to the question: What is the proper way to omit an entry from an Algolia index?

I've done this, and I believe the trick was to return true.

UPDATE: Looks like this was fixed in version 1.5.2, returning false will skip the entry as expected.


How to set index page as parent of a structure I don't know if it's possible, but what I would like is to have a structure with 3 levels linked to a single entry that would act as the index. The problem is the examples I've seen are only with 1 level structures, so what they do is they set the single index URI as services/ and then the structure URI as services/{slug}. This, for a level 3 structure, gives me services/level3slug.
I want to display the parent URI on the level 3 entries, but if I do services/{parent.uri}/{slug}, I end up having a URI that is services/level1slug/services/level2slug/services/level3slug. When I would just have services/level1slug/level2slug/level3slug.

Is there a way of setting the single page as parent of the structure so I can just do {parent.uri}/{slug}?

If I understand your question, you want to combine a Single and a Structure into the same family of URL's, something like this:

/services - (Single)

/services/service-01 - (Structure Entry)

/services/services-01/example-sub-service-01 - (Structure Entry)

/services/services-01/example-sub-service-02 - (Structure Entry)

/services/service-02 - (Structure Entry)

/services/service-03 - (Structure Entry)

As you rightly said, you would create a Single for your Services homepage and set the URI to services.

You would then create a Structure called "Servcies", and set the URI to:

{parent.uri ? parent.uri: '/services'}/{slug}

This nice bit of Twig checks if parent.uri is defined, and outputs it if it is. Otherwise (if the entry is top level in the structure, it just outputs /services/{slug}


Entry should not activated by default Would it be possible that when you create a new entry, it's not activated by default?

I know there is a "Draft" option...  But is there an option for this?

Best,
Marcel

You can change the default entry status in your section settings.

Example: If I would set the German toggle to disabled, all entries added to German local will be disabled by default.


craftcms/vue-asset Related Error on Craft and Plugin Update When updating my plugins or craft I get the following error...

Error: The "https://composer.craftcms.com/p/nystudio107/craft-imageoptimize-imgix/c642ab1cfc1bf5e4c9c3c265837b1e5201a6ed55436f1bbb47558a9c63a49384.json" file could not be downloaded (HTTP/1.1 404 Not Found)

Composer output: Package "craftcms/vue-asset" listed for update is not installed. Ignoring.
Loading composer repositories with package information
Updating dependencies

Doing a google on craftcms/vue-asset - it looks like it is depreciated - so I'm not sure why I would need it.

This should be fixed by P&T:

https://github.com/craftcms/cms/issues/5063

https://github.com/nystudio107/craft-imageoptimize/issues/171

https://github.com/nystudio107/craft-imageoptimize/issues/169


localized site - except home, every page gives me a 404 I have a newly published site, where the localization does not work properly.
https://www.nomadenschaetze.com/de/
When i switch to english, it shows the right englisch homoepage. Now, when i click
another englisch site, for example contact, it does not find the templates.
https://www.nomadenschaetze.com/en/contact
The url is fine, the links have the right domain-urls, but it always goes to the 404.
In my dev- environment though, it is working:
the content and navigation changes to english,
https://dev.nomadenschaetze.com/de/
i am very confused.
my general.php looks like this:
 // Production environment settings
    'production' => [
        'siteUrl' => array(
            'nomadenschaetze_de' => 'https://www.nomadenschaetze.com/de/',
            'nomadenschaetze_en' => 'https://www.nomadenschaetze.com/en/',
        ),
        'allowAdminChanges' => true,
        'devMode' => false,
        'baseUrl' => 'https://www.nomadenschaetze.com',
        'aliases' => [
            '@root' => getenv('ROOT'),
            '@nomadenschaetze_url' => 'https://www.nomadenschaetze.com',
        ],
    ],

i have craft 3, in my web folder are a de and en folder. no .htaccess in there in these language folder.
in the web directory i have a .htacces file
<IfModule mod_rewrite.c>
   RewriteEngine On

    # language starts with DE
    RewriteCond %{HTTP:Accept-Language} ^de [NC]
    RewriteRule ^$ /de/ [L,R=301]

    # else redirect to the English version
    RewriteRule ^$ /en/ [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>

in the root directory i had to add a .htaccess file, because i cannot change the root directory on the server to "web".
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?nomadenschaetze\.com [NC]
RewriteCond %{REQUEST_URI} !^/web/.*$
RewriteRule ^(.*)$ /web/$1

what i am doing wrong?

I finally found the solution!
i was not aware, that the document-root HAS to point to the /web folder.
There were old web applications on the server, which prevented
to change the root. So i made the .htaccess file, to redirect to the
/web folder.
But apparently, this is not going to work.
So keep in mind, to point to the right folder.


Module not loading unless bootstrapped I'm expanding my Craft website with a small Module, internal to this project. The module currently only defines a new input-field (extending craft\base\Field).

I have dumped the autoloader from composer and my config/app.php only contains the registration of this module:

<?php
return [
    'modules' => [
        'simple-markdown-editor' => [
            'class' => \codeisland\simplemde\MarkdownModule::class,
        ],
    ],
    'bootstrap' => ['simple-markdown-editor'],
];

This setup works and the new field shows up in the Admin CP. But: as far as I understand the bootstrap-entry, it's only needed if the module needs to be executed on every page render. The Craft documentation says as much:

  TIP: If your module doesn’t need to get loaded on every request, you can remove its ID from the bootstrap array.

Since the module only defines an input-field for the Admin CP, it doesn't need to be loaded on every request. But if I remove it from the bootstrap-array, it's not loaded at all.

Do I need to add additional config? Or am I just misunderstanding the documentation?

It does in fact need to be loaded on every request, because otherwise your EVENT_REGISTER_FIELD_TYPES event listener wouldn’t get registered, which is responsible for telling Craft that the field type exists.


My live preview for blog entries is not working on my computer, but is working for my account on other computers When I go to live preview to view my blog entry in draft mode, all I see is a white screen. My co-workers have tested under my account on their computers and it works just fine. Does anyone have any kind of insights for this?

Are you all using the same browser / operating system? Try testing in a recent release of Chrome, Safari, or Internet Explorer.


HTML being stripped/replaced by redactor on initialising despite being saved correctly When i enter HTML into redactor below it will strip out the first closing div and the second opening div leaving one col-md-6.  It actually saves it as I have below but as soon as redactor is re-initialised it strips out the closing and opening tag in the middle again.  This means no one can ever go in an edit the content as it will be a single column again once saved. Current setup of redactor is below and I have unchecked the clean HTML.

One Col

One Col

Redactor JSON config:

{
        buttons: ['html','formatting','bold','italic','unorderedlist','orderedlist','link','image','video'],
        plugins: ['fullscreen'],
        toolbarFixedBox: true,
        replaceDivs: false
        replaceDivs: false,
        paragraphize: false,
        removeEmpty: ['strong', 'em', 'span', 'p']
    }

Any ideas how I can get it just to accept the HTML we enter without problems?

Have you tried using the allowedTags attribute in your Redactor config?

$('#redactor').redactor({
    allowedTags: ['div','p', 'h1', 'h2', 'pre']
});

You can read about that here:

http://imperavi.com/redactor/docs/settings/clean/#setting-allowedTags


Search with dynamic results A couple questions...

1) How do these dynamic searches work? A excellent example is found at McMaster Carr website

2) Is there any search plugin like that for Craft? I did not see any.

You don't really need a "search" plugin for that. Craft has a brilliant Query Builder so it can be done really easily. Furthermore there is the Element Api which provides a JSON endpoint.

I suggest you to read the docs about Searching in Craft and about Queries in Templates.

If you wan't to search for entries containing these words, a specific length and a threadSize you could do

{% for entry in craft.entries.threadSize('and, >0, <80).length('and, >10, <100).search({
    query: 'socket head screws',
    subLeft: true,
    subRight: true
}).limit(10).all() %}

{{ entry.title }}

        Continue reading

{% endfor %}

That's basically it.

For advanced searches I would recommend to create a custom plugin. It's totally easy to search things in Craft so the need of a "default" plugins is not really high and it's faster to create a custom plugin than to find one that fits all your specific needs.


Installing CraftQL plugin I wanted to know if there is any way to install markhuot/craftql via the command line.

I tried to follow the one-liner instruction here:
https://github.com/markhuot/craftql#installation

composer require markhuot/craftql:^1.0.0

but after installing I don't see the options in the backend.

You should be able to install the plugin with
./craft install/plugin craftql. Composer will only download the package and add it to composer.json


Global nav with dynamic links across multiple sites We are currently working on using Craft to build out new versions of our site (in-house) and we have multiple sites that will share a global nav. Is there a way for one site to access the data in another site to update the global nav dynamically? I'm not sure if it's possible but I also know Craft is pretty magical.

The parent domain link and child domain link will hardly never change so that can stay static content; more so wondering about accessing the data in the child domain from parent/sibling sites.

example structure

parent domain link
  |-- child domain link
  |   |_
  |     |-- dynamic links
  |     |-- dynamic links
  |     |-- dynamic links
  |
  |-- child domainlink
  |   |_
  |     |-- dynamic links
  |     |-- dynamic links
  |     |-- dynamic links
  |
  |-- child domain link
     |_
       |-- dynamic links
       |-- dynamic links
       |-- dynamic links

At the moment, that's not possible with Craft itself. That might be possible in Craft 3, as cloning sites will be an option -- though all of your sites would also have to be in Craft. Not sure if sharing information between sites will exist in C3 or not though.

You COULD use Craft to create the navigation fairly easily. Then you could create a blank template (not extending your base layout) that only contains the navigation, and then loading that via AJAX on the other sites into a nav container div.


includeJsFile vs includeJsResource As a solution to keep things segregated and clean in git, we started developing websites for craft with templates in the template folder, and js, css, etc in a plugin.  So each website had our base plugin (standard stuff like font-awesome, foundation, jquery, etc) and their website plugin (any additional libraries and their custom css/js).  As an added bonus, our clients could look at the plugin page in the admin panel and see "oh, cool... my website is built by [studio name]!"

To load javascript and css, I used things like:

{% includeJsResource "pluginname/vendor/foundation/bower_components/modernizr/modernizr.js" first %}

We started to notice some significant speed issues.
So I switched to this:

{% includeJsFile "/assets/vendor/foundation/bower_components/modernizr/modernizr.js" first %}

the page loaded SIGNIFICANTLY faster.  Like, 3-7 seconds faster.  Which is a lifetime on the web.  The documentation doesn't appear to make any mention of this.

Why is includeJsFile so much faster?
Is it possible to use includeJsFile AND keep my resources in the plugin directory?

includeJsFile links directly to the file. It doesn't try anything fancy, it just finds the file (exactly as you've referred to it) and creates a normal <script> tag for it.

includeJsResource looks for that file in a few different places. It could be a plugin resource, it could be a native Craft resource, etc.

Whenever possible, stick to includeJsFile.


Creating a calendar event from within a plugin (stuck on saving) I'm trying to create an event from within a plugin. I've come up with the following:
$event = new Event(); // Solspace\Calendar\Elements\Event;
$event->authorId = 1;
$event->calendarId = 5;
$event->name = 'Hello name';
$event->title = 'Hello title';
$event->startDate = new DateTime();
$event->endDate = new DateTime();
$event->allDay = true;

But I don't understand how to actually save the event (e.g. $event->save()). Am I on the right track or completely off? I couldn't find anything on this in the docs.

I got help on Discord. The way to do it was Calendar::getInstance()->events->saveEvent($event); Edit: DateTime also needs to be replaced with Carbon()


How do I display a list of assets with the entries they are related to? Given a list of assets, for each asset, how do I display a list of entries that relate to this asset? So, for instance, if asset A is selected as asset in entries 1 and 2, I want a list to be displayed like this:

Asset A:

Used in entry 1
Used in entry 2

Asset B:

Used in ... etc.

With this ...

{% set content = craft.entries.section('content').find() %}
{% set usedFotos = craft.assets.relatedTo(content).find() | group('id') %}

... I can see if certain assets are used, but now I want to see what entr(y/ies) they belong to.

You probably have to query a new ElementCriteriaModel for each asset in your loop and use the relatedTo parameter to filter the relevant "content" entries.

You could use the targetElement property with the relatedTo parameter to be more spezific on that relation. But you should be fine using the element property or the short syntax relatedTo(element), if you don't do any (reverse) relations (e.g. with an entries field as an asset meta field).

Tested this on an install with 400 images and yes, you want to wrap it in cache tags!

{% set content = craft.entries.section('content').find() %}
{% set usedFotos = craft.assets.relatedTo(content).order('filename').find() %}

{# Loop throught the array of assets #}
{% for usedFoto in usedFotos %}

{{ usedFoto.filename }}

        {# Loop throught entries related to this asset #}
        {% for entry in craft.entries.relatedTo(usedFoto).order('title') %}

{{ entry.title }}

        {% endfor %}

{% endfor %}


How to get the unique categories from a list I have a set of FAQ entries. Each entry has one or more categories attached. To be able to filter entries related to a category I need a list with unique categories.

Using my solution I'm getting all (some double) categories.

   {% set entries = craft.entries.section('faqs') %}
   {% for entry in entries %}
        {% for category in entry.faqCategory %}

{{ category.title }}&nbsp;

        {% endfor %}
    {% endfor %}

Maybe not the most elegant, but something like this should work:

{% set entries = craft.entries.section('faqs') %}
{% set usedCategoryIds = [] %}

{% for entry in entries %}
    {% for category in entry.faqCategory %}
        {% if category.id not in usedCategoryIds %}

{{ category.title }}&nbsp;

            {% set usedCategoryIds = usedCategoryIds|merge([category.id]) %}
        {% endif %}
    {% endfor %}
{% endfor %}


Viewing Assets (PDFs) associated with an entry directly from that entry screen I have a channel with an Assets field, designed to hold PDF files. It works fine to select one or more files, and/or upload files and select them. However, I'm wondering if there is a way to view a PDF once selected, from the add/edit entry screen.

I'm guessing you may have found an answer to this, but have you seen the download assets plugin? It puts a download button next to every asset on an edit page that links to the asset's url.


How do I hide a login form if user is logged in? What conditional statement would hide a form if a user is logged in?

The Twig variable currentUser contains information about the currently logged in user, and will be null if no user is currently logged in.

{% if not currentUser %}

    <!-- Your login form -->

{% endif %}


Display only entries relevant to users' country I'm really struggling with displaying news entry that are only relevant to the users' location.

Here is my structure:

User

Country - > is a dropdown with a single value (lets say UK)

Regions is a category that contains

name -> string (for example Europe)

countries -> a checkbox with a list of countries (UK, FR.. etc)

News which has a Region category

So what I have now is this:

{% for entry in craft.entries.section('news') %}
{# loop through regions  #}
    {% for region in entry.regions %}
        {# loop region's countries  #}
        {% for targetCountry in region.countries %}
            {% if targetCountry == currentUser.country %}
                {% set visibility = true %}
            {% endif %}
        {% endfor %}
    {% endfor %}
{% endfor %}

This works, however, since the checking occurs after I get all the entries I can't use pagination. Is there a nicer way of doing this?

One nice way to handle things like this is to collect the ids for all the entries you want, use those ids for the ElementCriteriaModel you need for the pagination, and then paginate.

Collect the ids (use merge to create an array of the ids):

{% set ids = [] %}

{% for entry in craft.entries.section('news') %}
  {# loop through regions  #}
  {% for region in entry.regions %}
    {# loop region's countries  #}
    {% for targetCountry in region.countries %}
      {% if targetCountry == currentUser.country %}
        {% set ids = ids | merge([entry.id]) %}
      {% endif %}
    {% endfor %}
  {% endfor %}
{% endfor %}

Get the entries for pagination:

{% set unpaginated = craft.entries({
  id: ids,
  limit: 10
}) %}

Finally, the pagination:

{% paginate unpaginated as pageInfo, pageEntries %}
...


How to check an elements elementType In Craft 3, I've got a service function that I'm passing either an 'entry' or 'category' element into.

I'd like to know how to differentiate between the possible element types; This kinda of works:

public function getElementType($element) {
  if ( isset($element->group) ) {
    return = 'category';
  } else if (isset($element->section)) {
    return = 'entry';
  }
}

However I can't help but feel this is unreliable and hacky. Is there a better way to check an elements elementType?

Having arrived here from a Google search while trying to do this in Twig rather than PHP, I thought it might help someone in future to leave an answer, even though it doesn't address your question directly:
{{ item is instance of('craft\\elements\\Entry') ? 'This element is an entry!' }}
{{ item is instance of('craft\\elements\\Asset') ? 'This is an asset!' }}
{{ item is instance of('craft\\elements\\Category') ? 'This is a category!' }}
{{ item is instance of('craft\\elements\\User') ? 'This is a user!' }}

I find this especially useful in, for example, internal keyword search results listings templates, where the elements that were found might be of different types and you want to take different actions depending on the types.


Show Entries based on content in a Matrix Field I have a product with a variant matrix field(productVariants). Inside each variant is the option to supply a sale price (salePrice).

On the front end, I'm trying to show a product grid of only products that are on sale. Sounds simple, but I can't for the life of me figure out the syntax.

Here's where I'm at so far using matrixBlock queries. A few things I am not clear on:

owner - what is the owner? Docs only say myEntry and I'm not on a page or in a loop to get the entry that the matrix field is a part of
fieldId - is this the matrix field ID or the ID of the text field with the value I'm searching for?
How do I target salePrice in the search syntax since it's one of the fields inside the Matrix field?

{% set myMatrixBlockQuery = craft.matrixBlocks.owner(myEntry).fieldId(33).type('text').search('salePrice:*') %}

{% set saleEntries = myMatrixBlockQuery.all() %}

{% for product in saleEntries %}
{{ product.title }}, etc...
{% endfor %}

I've spent a couple of hours in StackExchange and in the Craft docs and still can't wrap my head around the syntax for this situation so I appreciate your help!

I was finally able to piece this together using Brad's explanation of MatrixBlocks parameters and this thread Can I get an entry by Matrix Block ID?

Seems merge([block.owner.id]) was the piece I was missing to fold the MatrixBlock query back into an entries loop.

{# Find Matrix Blocks with field value #}
{% set blocks = craft.matrixBlocks.type('variant').fieldId(33).salePrice(':notempty:').all() %}

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

{# Get entries with limit #}
{% set saleProducts = craft.entries.section('shop').id(saleEntryIds).limit(4) %}

{% for product in saleProducts.all() %}
    {{ product.title }}
    {% for block in product.productVariants.all() %}
        {{ block.salePrice }}
    {% endfor %}
{% endfor %}

Seems a little overly complicated - maybe there's an easier way to do it?


Decimals missing in result after adding up order totals for a customer I want to show a user the total sum of all their orders.
My problem: In the result the decimals are "lost" and always show as zeros.

{% set totalOrders = 0 %}
{% for order in craft.commerce.orders.customer(craft.commerce.customer).find() %}
  {% set totalOrders = totalOrders + order.totalPrice|currency(order.currency) %}
{% endfor %}
{{ totalOrders|currency(order.currency) }}

The trouble you are running into is trying to add a string value to an integer to get your total.

You have to use order.totalPrice without the currency filter to be able to add all the values together.

{% set cart = craft.commerce.cart %}
{% set totalOrders = 0 %}

{% for order in craft.commerce.orders.customer( craft.commerce.customer ).find() %}
  {% set totalOrders = totalOrders + order.totalPrice %}
{% endfor %}

{{ totalOrders|currency( cart.currency ) }}

Only apply the currency filter once all the calculations are complete.


Changing status via entries list in one locale also (unexpectedly) changes status in other locale(s) I'm not certain if this is expected behavior but if so the user experience is confusing/unexpected:

When viewing a list of entries in the control panel, swapping between locales shows the expected statuses--either enabled or disabled--for each entry. Accordingly, example, an entry that is enabled in English but disabled in Spanish, is properly displayed as such. However, making a change to the status when switched to either locale applies the status to both locales, rather than just the selected locale.

This seems to indicate that adjusting statuses through the entries list applies only to the entry's master enabled/disabled status, not the selected locale's status (which was my expectation). Should this be the be case? I found out the hard way by switching to my Spanish locale, selecting all entries, and then setting their status to disabled. Switching to the other status showed that they too had been disabled. Bummer.

Any thoughts or similar experiences? Did I miss something in the docs?

Cheers.

I agree this is confusing.

If you are editing the entry, you can change the status per/locale by selecting the locale in the box in the upper right corner, and then using the lightswitch next to the selected locale.


Is there any easy way (via the admin panel) to get a direct link for an asset? A client wants to be able to get URLs for assets (for, eg. pasting a direct link into an email). For images and PDFs, "View file" works nicely (the file opens in a new browser tab), but for other file types which the browser can't display, they download instead. Is there any way of accessing the full URL of an asset from within the admin panel?

(The best I've been able to suggest is that they reconstruct the URL from the folder structure of their assets, so, eg. "Files > Documents > File.xls" becomes /assets/files/Documents/File.xls, but it would be great if there was a less fiddly way of getting that URL)

You could utilize the modifyAssetTableAttributes and getAssetTableAttributeHtml hooks.

So, you would create a plugin, and in the main plugin file you could add something like the following:

public function modifyAssetTableAttributes(&$attributes, $source)
{
    $attributes['filePath'] = Craft::t('File Path');
}

public function getAssetTableAttributeHtml(AssetFileModel $asset, $attribute)
{
    if ($attribute == 'filePath')
    {
        $filePath = $asset->url;
        return $filePath;
    }
}

* Edit *

I did test this, and it works, but because of Craft's ability to reorganize Assets (i.e., drag them to a new folder) it's not just a simple matter of highlighting the link, copying, and pasting.

However, by taking this example a little further, you should be able to add a little JS and have a link or something to that effect output in getAssetTableAttributeHtml that when clicked copies the URL to the user's clipboard. If you go this route, make sure to include the JS in your plugin's init method. Something like:

public function init()
{
    craft()->templates->includeJsResource('yourplugin/your-js.js');
}

Or (hah), for a really basic implementation, you could wrap the string in a URL and just have them right click and "Copy Link Address":

public function getAssetTableAttributeHtml(AssetFileModel $asset, $attribute)
{
    if ($attribute == 'filePath')
    {
        $filePath = 'url.'">' . $asset->url . '';
        return $filePath;
    }
}


Find entries with multiple start and end dates from the same date field I've got a front end form where a user can select multiple months to find entries with dates in those months.
I had code that does that for one month, but now I need to expand that to multiple months.
{# craft.app.request.getParam('departure') format is going to yyyy-mm-dd #}

{% if craft.app.request.getParam('departure') | length %}
    {% set lastDay = craft.app.request.getParam('departure') [0:7] %}
    {% set lastDay = lastDay ~ '-31' %}
    {% set firstDay = craft.app.request.getParam('departure') %}
    {% set entries = entries.startsOn(['and', '>= '~firstDay, '< '~ lastDay]) %}
{% endif %}

I was trying to combine it as I have with other fields like so:
 {% set deptDates = [] %}
    {% set deptDates = deptDates|merge(['or']) %}
    {% for dept in craft.app.request.getParam('departure') %}

        {% set lastDay = dept [0:7] %}
        {% set lastDay = lastDay ~ '-31' %}
        {% set firstDay = dept %}
        {% set deptDates = deptDates|merge(['and', '>= '~firstDay, '< '~ lastDay]) %}

    {% endfor %}
    {% set entries = entries.startsOn(deptDates) %}

But, for obvious reasons, this didn't work :)
Any ideas gratefully received!

What an idiot.
I almost never use Advanced element queries which is why it never popped into my head I guess.
So you can add where() and orWhere() into your standard craft.entries calls.
So my code becomes
{% if craft.app.request.getParam('departure') | length %}
    {% for dept in craft.app.request.getParam('departure') %}
        {% set lastDay = dept [0:7] %}
        {% set lastDay = lastDay ~ '-31' %}
        {% set firstDay = dept %}
        {% set entries = entries.orWhere(
            ['between', 'field_startsOn', "#{firstDay}", "#{lastDay}" ]
        ) %}
    {% endfor %}
{% endif %}


Matrix entry causing last bootstrap column to be shunted down I have a Matrix field which has one block type (1 asset field - I'm using a Matrix field as I'll be adding text fields later on to the same block). On the front end I am using Bootstrap's grid system to output the images in columns.

{% for block in entry.blockName %}

    {% set image = block.image.first() %}
    {% if image %}

    {% endif %}

 {% endblock %}

For some reason when I test it the last column on the first row gets shunted down as shown in the image.

This only happens on the first row of items and if I test it out of the matrix field with placeholder images and static HTML it works fine. The CSS isn't changed for the last item so I can't seem to see what's causing this.

Anyone have any ideas?

This issue won't be related to the Matrix field or the twig tags outputting it - check the CSS thats being applied. Are you wrapping your columns in a div with a class of .row?

UPDATE: test by creating a new template and set it up with the following (replace the first line with the entry you're using:

{% set entry = craft.entries.section( 'homepage' ).first() %}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" media="screen">

        {% for block in entry.blockName %}

            {% set image = block.image.first() %}
            {% if image %}

            {% endif %}

        {% endfor %}


How is appID used in caching? I want to ensure that cache is set per domain at a config level. So rather than saying something like this in the template:

{% cache using key craft.config.getHostInfo ~ '.' ~ entry.slug ~ '.masterPrimaryNav' %}
    foo
{% endcache %}

I would like to set this in config so the cache key is prepended automatically. I had hoped that the general appId would help this on config, but I can't see that being set in the cache key when I set it: http://buildwithcraft.com/docs/config-settings#appId

Is there a way to do this?

appId wont help you there. If you take a look at the source code, you'll see how the appId is used in sessions.

I'm not aware of an automatic way to prepend cache keys.


How can I output ALL strings from a lang file? I need to output a JSON object containing all of the key/value pairs in either /translations/{myLocale}.php or /craft/plugins/myplugin/translations/{myLocale}.php.

I can't see any way of doing that?

I can see that I can call craft()->getComponent('messages') but that will retrieve all of Craft's internal translations - I only want the messages I have defined in one of the files above.

You could include the translations file into your controller:

$translationsFile = craft()->path->getPluginsPath().'myplugin/translations/de.php';
$translationsArray = include $translationsFile;

$this->returnJson(array_keys($translationsArray));


Auto-generated title based on last entry I am attempting to make one of my sections use auto-generated titles. I am making my first entry with a title like 8000. What I need is the second entry to be titled 8001, the third 8002, etc. Each entry must have a unique title in sequence.

This is the Title Format I tried using:

{{ craft.entries.section('scripts').last().title + 1 }}

I created a test entry after that and it successfully generated a title similar to the last entry plus one. However, when I created a second test entry, the title remained the same as the first test entry, but the slug was titlexx-1. I made another test entry, same thing, with the slug titlexx-2.

What am I missing in my Title Format?

Thanks for the help!

Something like this should do what you're looking for:

{% if not object.id %}{{ craft.entries.section('scripts').order('postDate DESC').first().title + 1 }}{% else %}{{ object.title }}{% endif %}


Move unused Assets to a specific Folder I would like to create a plugin/function to move all unused assets (which are not related to a entry) to a specific folder in the same assets source. Now i try to create the function to move a single file by referring the id of the file. But i get always errors... The function should look like this:

public function moveFileToFolder($fileId,$idOfTargetFolder,$assetSourceId) {
 ....
}

Thanks for any help!

I found the solution: The moveFiles function provide the function to move a file:

/**
* Move or rename files.
*
* @param        $fileIds
* @param        $folderId
* @param string $filename If this is a rename operation or not.
* @param array  $actions  Actions to take in case of a conflict.
*
* @throws Exception
* @return bool|AssetOperationResponseModel
*/

public function moveFiles($fileIds, $folderId, $filename = '', $actions = array())

So for me the following code works to move the file with the id 21 to the folder with the id 3:

craft()->assets->moveFiles([21], 3,'', "keepBoth");


Craft 3: fetching a single Matrix row by its dropdown field value I have 2 Matrix fields in an entry type, both of which use Dropdown fields:

Matrix: urls
    address (block type)
        context (dropdown field values include 'own')
        address
        urn

Matrix: logos
   svg (block type)
        usage (dropdown field values include 'monoNeg')
        aspectRatio
        svg (source code)
   img (block type)
        usage (equivalent dropdown field)
        img

Entries are assigned to a footer Globals field, from which I'm pairing a urls value with a logos value in a loop to write linked logos.

I can get the relevant URL easily enough with:

{% for org in footer.footerAccreditations %}
    {% set orgUrl = org.urls.context('own').one() %}
    {{ orgUrl.address }}
{% endfor %}

Which prints the address URL just fine.

But the same approach for the svg logo isn't working. Either one of the following returns 0, even when I know for sure that the org entry in question has a monoNeg SVG source.

{% set negLogoDirect = org.logos.usage('monoNeg').one() %}
{{ negLogoDirect|length }}

{% set negLogoTyped = org.logos.type('svg').usage('monoNeg').one() %}
{{ negLogoTyped|length }}

If I run through an all loop for the logos their usage reports exactly as I would expect:

{% set orgLogos = org.logos.all() %}

{% for logo in orgLogos %}
    {{ logo.usage }}
{% endfor %}

I assume I can make my template more verbose and get what I need, but I don't see why the same approach should work for one Matrix dropdown field and not for another.

Where am I going wrong?

That is most likely happening because usage is ambiguous for your logos field, so Craft isn’t sure which column to assign the condition to. If you give the usage field within your img block type a different handle, you should get reliable results.


Need Swift Mailer to send emails as UTF-8 I have a Craft 3 site that used Freeform Pro for a contact form. All submissions from this form need to be sent, via email to a third party vendor who parses the information and submits it to a CRM. The format for the emails they receive is very specific: plain-text, utf-8 character set.

When I send a test email from the contact form, it appears to default to ascii if there isn't a utf-8 character in the message. Is there a way to have SwiftMailer to send all emails as UTF-8?

Completely untested, but try setting this in your public index.php file right before Craft executes:

\Swift_Preferences::getInstance()->setCharset('UTF-8');

Based on https://swiftmailer.symfony.com/docs/messages.html#setting-the-character-set


Multiple Service/Variable/Controller plugin files I'm not sure if I missed documentation on it, but is there a method to follow when including additional plugin files for services, controllers, variables etc.?

For bigger plugins it'd help to do this, something like

- /myplugin
   -/services
      -MyPluginService.php
      -MyPlugin_OtherService.php
      -MyPlugin_AnotherService.php

I've tried doing this and being sure to follow the service structure of:

namespace Craft;

class MyPlugin_OtherService extends BaseApplicationComponent
{

  public function testing()
  {
      return "success!";
  }

}

But when trying to access it from say the myPluginVariable.php file, I get the CException error that the property is not defined.

return craft()->myPlugin_OtherService->testing();

Is there a step I'm missing? Do I need to declare these extra files somewhere so that they are included?

When calling services, you should not include "service" in method name.

Try return craft()->myPlugin_other->testing();


What happens if I change base currency If I set say NZD as the primary currency now and then change to USD or EUR down the track will I have to re-price the products or will they pick up the converted pricing?

I'm planning on having USD, AUD, NZD, EUR, GBP and using the Currency Layer plugin for live conversion rates.

Craft Commerce uses a conversion factor/rate to figure out how to price the others.

Once you add more than one currency to Commerce, it becomes a bit more obvious as to what's going on:

Once you set the Primary/Base currency, every other price will be derived from the base.

So, if you change the primary base currency, you're really only effectively changing the name and the conversion factor/ratio will also be off.

As noted in the docs, Commerce also doesn't keep that conversion rate up-to-date for you.

How to Change the Base Currency

To change the base currency, you would effectively want to change all your prices. However, that's not too difficult—you'd need to export all of your SKUs with the current pricing, change the base currency, and the conversion factors, then reimport the prices at the new base currency's rate.

You'd also want to update any shipping or tax rates as well if necessary.

One thing to consider is the store's base currency is the value you put into the CMS. However, you can show whatever currency you want to the user on the front end and show it as a "default".

If it were me, I'd choose the primary currency that the store's location uses or whatever you use to manage your books then expand out as necessary.


Create matrix block with no fields Is it possible to create a matrix block with no fields? I'm using matrix as a page builder and have several scenarios where certain matrix blocks simply act as true/false checks.

As an example, my Horizontal Rule block simply adds an '< hr >' tag to the page. No fieldtype is needed for this block.

I can add a dummy text field to the block that does nothing, but this is not too elegant. Any ideas?

I tend to design my matrix block at a slightly higher level. I would have a text block with the rich text editor that allows you to enter a <hr/> tag. You can obviously also use this for all other text on the page, no need for multiple text style blocks.

You would add new block types for rich media components like galleries, videos, widgets, etc.

I know this is not exactly what you are looking for, maybe someone else will have an approach that works for your scenario.


Can't access data in Matrix field Stuck on a problem at the moment… trying to output a Rich Text field (copy) from an entry. The copy is contained in a matrix field (so: Entry -> Matrix Field -> Copy Field) but I can’t access it no matter what I try.

The Matrix Field Type is genericContent, the entry is relatedContent and the copy field is simply named copy.

Here's the code I currently have, I've tried various other options but none work.

{% set entries = entry.relatedContent %}

{% for entry in entries %}
    {% switch entries|length %}
        {% case '1' %}
            one
        {% case '2' %}

                    {{ entry.sectionTag.first }}

{{ entry.title }}

{{ entry.genericContent.copyMatrix.copy.first }}

{{dump(entry.genericContent.copyMatrix.copy.first)}}

        {% case '3' %}
            three
        {% case '4' %}
            four
    {% endswitch %}
{% endfor %}

You're close! The relatedContent field is an ElementCriteriaModel, so you need to loop over it (or otherwise treat it somewhat like an array) to get to the entries.

The matrix field is also an array like thing, and you need to loop over it to get at the blocks. See here

Here is what I would do (assuming the matrix field handle is genericContent:

{% for oneRelatedContent in entry.relatedContent %}
  {% for block in oneRelatedContent.genericContent %}

        {{ oneRelatedContent.sectionTag.first }}

{{ oneRelatedContent.title }}

        {{ copy }}

  {% endfor %}
{% endfor %}

You want to use loop.index to tell you which matrix block this is.
If you need to count the entries in relatedContent, you will need loop.parent.loop.index Loop variable


being replaced by  tags in redactor rich text editor I have read previous questions and answers about the redactor rich text editor but in this version of Craft i only found simple.json and standard.json under craft/config/redactor. I have tried with both but <div> tags are still replaced by <p>. Is there another way to add <div> into a redactor rich text field?

You can create a new redactor config under craft/config/redactor named Simple-With-Divs.json with the following code:

{
    buttons: ['bold', 'italic'],
    toolbarFixed: true,
    replaceDivs: false
}

Now you can select Simple With Divs under the Rich Text field type.


Include entries to a entries section object, without 'merge' So I have a structure with a few entries and a single. I want to list out the first level of the structure, plus the single. Then somewhere else, list out the second level.

I've tried the following:

{% set myPages = craft.entries.section('structureName')|merge(craft.entries.section('singleName')) %}

<nav>
{% nav entry in myPages.level(1) %}
  {{ entry.title }}
{% endnav %}
<nav>

<aside>
{% for entry in myPages.level(2) %}
  {{ entry.title }}
{% endfor %}
<aside>

Which returns this error:

  "Array to string conversion"

When I remove the .level(X) function it will return all the entries, on all levels; including the single.

For the purposes of making my problem more understandable, I've simplified my above example. I know I could just add the single entry directly into the <nav>. But I'm curious about ways to add to a entries section object without losing the ability to query levels.

So, in the same way I can exclude entries, is there a way to include an entry from a different section without relying on Twigs merge filter?

A colleague of mine shed some light on a very simple solution

{% set myPages = craft.entries.section(['structureName', 'singleName']).order('sectionId desc') %}

<nav>
{% nav entry in myPages.level([1, null]) %}
  {{ entry.title }}
{% endnav %}
<nav>

<aside>
{% for entry in myPages.level(2) %}
  {{ entry.title }}
{% endfor %}
<aside>

Passing an array of handles/slugs instead of just a string works perfectly. Since singles don't have levels; defining null in the level pulls them out too.


Sorting categories by the post date of the entries related to them I need to sort my categories based on the date of entries returned within the category. I am trying to sort sermons from a church by the series they were contained within. I have the sermons grouped by their series and outputting correctly on that front but they display in order based on the category creation date.

I need the sermon series to show in chronological descending order.

So we have Sermon Series A, Sermon Series B, Sermon Series C... within each one of those categories we have individual sermons related to the category. For example:

Sermon Series B

Sermon 1 (1/10/2013)
Sermon 2 (1/17/2013)

Sermon Series C

Sermon 1 (9/10/2014)
Sermon 2 (9/17/2014)

Sermon Series A

Sermon 1 (5/10/2014)
Sermon 2 (5/17/2014)

Currently my output looks very similar to the above example but what I need is for it to show like this:

Sermon Series C

Sermon 1 (9/10/2014)
Sermon 2 (9/17/2014)

Sermon Series A

Sermon 1 (5/10/2014)
Sermon 2 (5/17/2014)

Sermon Series B

Sermon 1 (1/10/2013)
Sermon 2 (1/17/2013)

Since the entries contained within the categories are in that order by post date.

Here is my current Twig code:

{% set entries = craft.entries.section('sermon').limit(null) %}

{% for category in craft.categories.group('sermonSeries').relatedTo(entries).order('dateCreated desc') %}

  {% for entry in entries.relatedTo(category) %}

But as I stated above this doesn't output my content with the desired effect.

Alan,

Without having tested this, you might get the desired result by using the group filter.

So, get all you entries ordered by dateCreated, and then group them by category:

{% set sermons = craft.entries.section('sermon').order('dateCreated desc').limit(null) %}
{% for category, catSermons in sermons | group('categoryFieldHandle.first().title') %}
    <li>{{ category }}
        {% for sermon in catSermons %}
            <li>{{ sermon.title }}</li>
        {% endfor %}
    </li>
{% endfor %}

Let me know if that works!


Freeform plugin unique submission amount I'm needing to get the unique entry submission amount for a value.

Example:
Item1, Item2, Item1, Item3, Item1

Would return:
3

I was able to use the workaround here Search/Filter Freeform submissions by field value to get the specific submission amount but only wanting to know the number of unique submission values.

Can anyone help?

Looks like there's a Craft 2 plugin that exposes PHP's array_unique method to Twig.

So to continue on the example you linked to, it would be something like this with that plugin installed:

{# Initiate the hash in which we'll store matching submissions. #}
{% set matchingSubmissions = [] %}

{#
    Loop through all submissions, checking if the specified field
    matches the desired value.
#}
{% for submission in submissions if submission.fieldWithValue == '123' %}

    {# If the field matches, add it to the hash #}
    {% set matchingSubmissions = matchingSubmissions|merge([submission.fieldWithValue]) %}

{% endfor %}

{# Count the size of the resulting hash and save it. #}
{% set totalUniques = matchingSubmissions|unique|length %}


amforms - Specific entry in the notification template How can I get a specific value from the submitted form? E.g. the fullName field.

The default template loops through all the fields with a switch but I just want to output one specific field. Can't get it to work.

You can get the value of a specific field by using

{{ submission.fieldHandle }}

E.g.

{{ submission.fullName }}


Adding additional custom fields to Contact Form Plugin from Pixel & Tonic I'm working with the P&T contact form plugin:
https://github.com/pixelandtonic/ContactForm

And I can't figure out how to add additional fields to my email, where do I add the additional field to the email template?

Thanks is advance.

MORE INFO:

Error Message:

Internal Server Error
Property "Craft\ContactFormModel.company" is not defined.

HTML Email Form:

$email->body = "Your Name: ".$message->fromName."\n\nCompany:\n\n".$message->company."Email Address: ".$message->fromEmail."\n\nPhone Number: ".$message->phone."\n\nRequests: ".$message->message;

I'd start by reading the "Adding Additional Fields" part of the docs. ;)


Craft hosted on Google App Engine - failing to load Craft classes? Have tried getting Craft working on Google App Engine (GAE) using the GAE SDK and after defining CRAFT_STORAGE_PATH first up in the index.php, setting it to a Google Cloud Storage path eg. gs://craft-gae-storage/ I found I had to uncomment the workings of craft_ensureFolderIsReadable function in bootstrap.php so it didn't fail on the folder checks, but then it still dies with the error:

Fatal error: Class 'Craft\PhpMessageSource' not found in /Users/.../Craft-gae-HappyLager/craft/app/framework/YiiBase.php on line 213

I'm using the HappyLager demo combined with the Yii GAE codebase from https://github.com/poul-kg/yii-app-engine with a slightly modified base setup to try to get craft working:
https://github.com/moldedjelly/craft-gae

I got the same error and started debugging with XDebug.

I've put some hours in this and my conclusion is: You can't run Craft on GAE. It gets worse: You can't even run Yii1 (the framework Craft was built on) on GAE. So that's where it stops.

I did manage to get Craft running on a GAE development server instance, but to do that I had to uncomment every filesystem check in both Craft and Yii (functions like is_dir(), etc). These functions don't even work with the gs:// wrapper.


Fixed order with limited set, then resume normal order I have a news page (/news). You can open an article (i.e. /news/test-article) which uses the same listing template, but has an accordion open with content for that article (javascript/push state magic).

In the event someone goes directly to /news/{slug} I want to make sure that article is the top one in the list.

Is it possible to go i.e.

$criterea = craft()->elements->getCriteria(ElementType::Entry);
$criterea->section = 'news';
$criterea->order = 'postDate desc';
$criterea->ids = [$startArticle->id, {magically fall back to default sorting!}];
$criterea->fixedOrder = true;

Or am I going to have to futz with the array manually after the search?

Thanks.

Isn't news/test-article just an example of news/{slug}? And is this for a plugin (hence the PHP) or a template (hence the templating tag for your question)?

Perhaps what you want to do is start by grabbing the slug from the URL and getting the entry you're after:

{% set entry = craft.entries.section('news').slug(craft.request.lastSegment).first %}
// output

Use that to display the first entry, then get the rest of the news entries but filter out the active:

{% set otherEntries = craft.entries.section('news').id('not ' ~ entry.id) %}
{% for otherEntry in otherEntries %}
    // output
{% endfor %}


How could I include another template on a click with ajax? I am a newbie with ajax and I have to display a template only when clicking on a button. This template is weighing and it will be on all pages, so I want to use ajax.

Someone can help me?

Primarily, this is a Javascript question, not a Craft CMS question. For the Javascript part of this, I would look for general AJAX tutorials or try searching on Stack Overflow.

But rather than downvote this question as being off-topic, here are some things to help on the Craft CMS side of things.

You can create a template to generate a chuck of HTML you want to include in other pages.

For example, if you create a file called:

/templates/includes/example.twig

You can access that from http://mysite.com/includes/example no matter if it's directly in a browser or thru an Ajax request from another page.

If you need to test wether a template is being accessed directly thru a browser or an Ajax request, you can test that with craft.app.request.isAjax:

{% if craft.app.request.isAjax %}
  Yep
{% else %}
  Nope
{% endif %}

If you'd rather have your Javascript deal with JSON data instead of a chuck of HTML code, you have a few options.

You can name a file with the .json extension and file-based routing will automatically serve that URL as the content type 'application/json'.

/templates/includes/example.json

Or you can use the Element API plugin. This is a much more performant solution, but require some PHP knowledge.


How to merge/combine/transfer-entries-between two categories in the CP? I’ve got 2 categories each with lots of entries. The client wants to delete one category, and transfer it’s entries into the other one.

If I delete the category, it just disappears, but I somehow need to mass assign all those entires into another category without going through each entry manually.

Any ideas welcome.

This could easily be accomplished with a MySQL query on your DB. Of course, BACK UP YOUR DATABASE FIRST!

Example, assuming the old category ID is 1 and the new one is 2...

UPDATE `craft_relations`
SET `target_id` = 2
WHERE `field_id` = [your field id] AND `target_id` = 1;


Limit search by channel on the form rather than the results template I'd like to use the same results template for all of my search functions so I'm wondering if it's possible to limit the search to a specific channel i.e. news or calendar in the form rather than in the results template.

Thanks!

You'd do it just like querying for any other element in Craft.  i.e.

{% set results = craft.entries({
    search: query,
    section: 'news'
}) %}


Some paths and settings being ignored in config I've tried to set some things in my general.php config file but they're being ignored.

I have the following but all are being ignored. For example, when the user receives the activation email, upon clicking the link the account is activated but they're not taken to my template 'user/activation-success' but instead the homepage and also not automatically logged in, like I'm setting. Any ideas?

return array(
    'setPasswordPath' => 'user/set-password',
    'activateAccountSuccessPath' => 'user/activation-success',
    'autoLoginAfterAccountActivation' => true
);

I'm running 2.5.2757.

Updated to show my full config file:

<?php

return array(
    'setPasswordPath' => 'user/set-password',
    'activateAccountSuccessPath' => 'user/activation-success',
    'autoLoginAfterAccountActivation' => true,

    '*' => array(
        'omitScriptNameInUrls' => true,
    ),

    '.local' => array(
        'devMode' => true,
        'userSessionDuration' => false
    ),

    '.co.uk' => array(
        'cooldownDuration' => 0,
    ),

    '.com' => array(
        'cooldownDuration' => 0,
    )
);

You're close!  Those config settings are off in no-mans-land right now.  If you want them to apply across all of your multi-environment configs, you need to move them into the '*' array like so:

return array(

    '*' => array(
        'omitScriptNameInUrls' => true,
        'setPasswordPath' => 'user/set-password',
        'activateAccountSuccessPath' => 'user/activation-success',
        'autoLoginAfterAccountActivation' => true,
    ),

    '.local' => array(
        'devMode' => true,
        'userSessionDuration' => false
    ),

    '.co.uk' => array(
        'cooldownDuration' => 0,
    ),

    '.com' => array(
        'cooldownDuration' => 0,
    )
);


How to search for content in a specific Matrix field? I'm not entirely sure how to search a specific Matrix field for a given bit of content. I can use:

{% for cta in entry.homeCtas.search('"Lorem Ipsum"') %}

{{ cta.ctaTitle }}

{% endfor %}

to find any Matrix rows with "Lorem Ipsum" (not in a specific field). But when I try something like this:

{% for cta in entry.homeCtas.search('ctaTitle:"Lorem Ipsum"') %}

{{ cta.ctaTitle }}

{% endfor %}

It returns nothing. Is my field syntax incorrect? Am I missing something obvious?

What I'm not clear of is if you are asking if you can query for entries that have a matrix field that contains x, or if you just asking if you can search within a matrix field of an entry that has already been returned by a query.

If it is the later, the following solution would work. This isn't a feature of Craft, but a feature of Twig. Thus, implementing it won't save on queries or anything, but it will help you filter the results returned by Craft.

Twig has a feature that allows you to apply a condition in addition to the for loop. It is documented here.

{% for cta in entry.homeCtas if cta.ctaTitle == "Lorem Ipsum" %}
    <h1>{{ cta.ctaTitle }}</h1>
{% endfor %}


Import local image with FeedMe assumes wrong folderId I am importing Entries from Google Spreadsheets and I have a column in my spreadsheet containing the filename of an image already existing in Craft.
The import itself works, but images are not found / not selected in the asset field.
In the logs I can see that the image query is wrong, it looks like that:
Search for existing asset with query {"siteId":1,"status":null,"folderId":1,"kind":null,"limit":"9","filename":"test-container-3.png","includeSubfolders":true}
The filename is correct, however the folderId is wrong, it should be 2.
I tried working with plain filenames like "test-container-3.png", I also tried prepending an alias pointing to the correct folder (absolute URL) like "@importImages/test-container-3.png". Made no difference.
How does FeedMe decide to use folderId 1 in its query? How can I change this?

So, I found the problem / solution myself:

I have 2 file volumes in my Craft installation (documents, images)
The asset field I am trying to fill via FeedMe is in its configuration limited to the "images" file volume, but the default location for uploads is (erroneously) configured in the documents share.
In this case, FeedMe is determining the folderId from the default location for uploads.
The same thing happens, if all volumes are configured for selection, so in my eyes this is a bug, which I filed here (https://github.com/craftcms/feed-me/issues/833)
So after changing the default upload location of my asset field to be where my files are actually located ("images" volume), everything works.
The column value needs to be the filename only, no alias or anything else prepended.


Render markdown as GFM (GitHub Flavored Markdown), therefore preserving line breaks? In particular, I'm trying to render the text in markdown preserving the original line breaks, like in the GitHub Flavored Markdown specifications.

Using {{ something | md }} in a template the output contains a line break only if a line ends with two spaces, like in the original markdown implementation.

Some markdown processors (ie Blackfriday, written in Go) call this feature "hardLineBreak".

I was able to get good results using {{ block.myFieldName|nl2br|markdown }}


How to search using partial words? Is it me, or can we not search using partial words in Craft CMS? This seems to be the case in the backend when search entry titles or assets, but a client has recently pointed it out on the front-end as well.

For example, we've got an entry title containing the word 'Peruvian' but searching for 'Peru' returns no results, while searching for 'Peruvian' does return a result.

That's because Craft doesn't do fuzzy searching by default.  You'd need to use the wildcard 'Peru*' to match 'Peruvian'.  You can see the full list of supported search syntaxes here: http://buildwithcraft.com/docs/searching

Related, you might want to vote for this feature request: http://feedback.buildwithcraft.com/forums/285221-feature-requests/suggestions/8459443-add-option-to-enable-fuzzy-search-as-default

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


Conditional anchor in structure url I have a structure section, where the last child should be an anchor in the slug:

parent/parent#child

I'm trying to setup conditional url formats on nested entries as such:

{parent.uri}{% if object.getDescendants().total() != 0 %)/{% else %}#{% endif %}{slug}

I've also tried the simpler

{parent.uri}{% if object.hasDescendants %)/{% else %}#{% endif %}{slug}

but keep getting stuck tasks when re-saving entries. Can someone tell me what I'm doing wrong? Thanks in advance

There was a typo hidden in there, otherwise the logic works. To get children as anchors in a structure, the following should do the trick:

{parent.uri}{% if object.getDescendants().total() != 0 %}/{% else %}#{% endif %}{slug}


How URL Mapping Works I am new to Craft and I am trying to figure out how routing works. When I click on an entries nav item, it makes a request to:

.com/index.php?p=admin/actions/elementIndex/getElements

The url of the item is .com/entries/affiliates and the call is ajax.

There is a section called affiliates, but the 'template' field is Null. I can't seem to figure out where the response is coming from.

There is an overview of how routing works in Craft here: https://craftcms.com/docs/routing and that guide works for front-end routing as well as Craft's own control panel routing when deciding which (if any) templates to render.

The call to p=admin/actions/elementIndex/getElements is a control panel AJAX action request (#3 is the routing list) that's going to the craft/app/controllers/ElementIndexController.php's actionGetElements method and returning data.


Strip styles option in Rich Text field? Is there a way to add a button to remove the current styles inside of a Rich Text field? I know there are options for customizing the toolbar, but I haven't found anything about removing styles. Any ideas?

Found this that works well. Reverts to p tags or normal text:

https://bitbucket.org/kreisvierdigital/redactorremoveformat


Detect device screen size in craft cms How can I get the screen size in craft cms? I mean the device width in px, so for example I can get a static map image with the exact size to fit the device screen

I think you are going to struggle with this in Craft, you would need to do it through Javascript.

Craft runs off PHP which is a server side scripting language, you need a client side scripting language.

Here is a good question which should help you with this: Get the size of the screen, current web page and browser window


Create line breaks from text field I'm looking for a way to output line break from a text field.

I'm aware of the "Allow line breaks" option and I have set that to true. I've then entered text with multiple new lines. However, when this text gets output in the template, there are no line breaks.

I have tried using Twig's new line to br function, like this:

{% set address = contact.address|nl2br %}

but this creates
 tags in the text, not the markup - that is, you can actually see the
 in the browser and no actual line breaks are being created.

Am I doing something wrong here? Are there any alternative solutions?

Thanks!

Expanding from Pascal Mollet's answer, this was the solution I came up with.

First setting the address variable with the |nl2br filter:

{% set address = contact.address|nl2br %}

Then, outputting that variable with the |raw filter:

{{address|raw}}

Using them both together at once like this (as Pascal suggested):

{% set address = contact.address|nl2br|raw %}

didn't work.


Is it possible to output the name of a Matrix Block? I'd like to output the Names of Matrix Blocks. I know you can filter by block types e.g.

{% for block in entry.myMatrixField.type('text, heading') %}
{% if block.type == "heading" %}
    <h3>{{ block.heading }}</h3>
{% else %}
    {{ block.text | markdown }}
{% endif %}
{% endfor %}

I know I could use {{ block.type }} and get the block type's handle but, I want to included the actual Name of the block type itself too.

For example, something like this:

{{ block.type.name }}

Is this currently possible?

block.type is actually an alias for a getType() function, which returns a new MatrixBlockTypeModel object. Those will output their handle by default, which is why it's possible to compare block.type  against block type handles. But MatrixBlockTypeModel also has a handle property, so this is totally possible:

{{ block.type.handle }}


block.image.one() shows more than one image I'm sure I'm doing something wrong here, but I'm at a loss as to what. I'm using Craft 3. My travel entry has 7 fields, one of those being a matrix field. My matrix has two blocks, postText and postImage.

Here's the bit of code I'm working with:

{% for block in entry.mainPost.all() %}
  {% if block.type == "postImage" %}
    {% set image = block.image.one() %}
        {% if image %}
            <img src="{{ image.getUrl('summaryImage')}}" alt="">
        {% endif %}
  {% endif %}
{% endfor %}

I have an entry that has two images in the Matrix field. When I load the page, both images load. The documentation states that using .one() "Returns the first matching element". I have to assume that I'm not understanding the ElementCriteriaModel or Assets or the way Matrix works or something.

Yes you're correct, one() will get the first matching element. However, in your code you're not asking for the first image block, but rather the first image from each image block (because each image field can have multiple images attached to it).

The structure is basically something like this:

entry          <- 1. The entry
  mainPost     <- 2. The matrix field
    postImage  <- 3. The matrix field's block
      image    <- 4. The field inside the matrix field's block

We want to get the first result from #3 but you're currently only asking for the first result from #4. (It is probably a good idea to also ask for the first result from #4 as well btw.)

I think something like the following would work in your case:

{% for block in entry.mainPost.type("postImage").limit(1).all() %}
  {% set image = block.image.one() %}
  {% if image %}
    <img src="{{ image.getUrl('summaryImage')}}" alt="">
  {% endif %}
{% endfor %}

UPDATE: looks like you actually need to use limit() instead of one() when querying for the block.

UPDATE 2: tacked on the all() to fix the deprecation!