Craft 3: Recognize cookies created in Craft 2

After a lot of trial & error, it turns out this is not possible. (At least, not by me.)

I was able to retrieve the raw Craft 2 cookie data using the following code...

// Generate hash of Craft 2 cookie
private function _getCraft2CookieHash()
{
    $newBasePath = Craft::$app->getBasePath();
    $oldBasePath = str_replace('vendor/craftcms/cms/src', 'app', $newBasePath);
    $appId = sprintf('%x',crc32($oldBasePath.'Craft'));
    return md5('Yii.Craft\UserSessionService.'.$appId);
}

// Get existing Craft 2 cookie data
public function getExistingCookieData()
{
    // Get name of Craft 2 cookie
    $craft2CookieHash = $this->_getCraft2CookieHash();
    $craft2CookieName = $craft2CookieHash.'MyCookie';

    // If Craft 2 cookie exists
    if (isset($_COOKIE[$craft2CookieName])) {

        // Get value of Craft 2 cookie
        $cookieValue = $_COOKIE[$craft2CookieName];

        /**
         * THIS IS WHERE IT ALL FELL APART
         * The cookie data is too highly encoded.
         */

    }
}

I was able to correctly determine the hash which makes up part of the Craft 2 cookie's name. Keep in mind, this only works if the site's folder structure did not change. The docs give you two different ways to upgrade the site from Craft 2, and this hash-detection logic will only work if you choose to "keep your current directory structure".

However, things really fell apart when trying to get the actual data from the cookie. The data is encoded in some very complex ways. In Craft 2, it uses a complicated function called computeHMAC which goes way beyond my understanding of security. There is no equivalent function in Craft 3 (and if there was, it would probably operate quite differently).

Sadly, I have to throw in the towel and admit defeat here. Backwards engineering the computeHMAC function is more than my puny brain can handle. :(


How to pull an entry's SEOmatic meta tags with Element API?

SEOmatic has some functions that it uses for its controller endpoints for returning metadata for SPAs and the like:

SEOmatic headless SPA APIs

We can leverage these for our own purposes in an Element API endpoint, if for some reason you can't ping the SEOmatic controller via AJAX or use GraphQL to access the data.

use nystudio107\seomatic\helpers\Container as ContainerHelper;
use nystudio107\seomatic\models\MetaJsonLdContainer;
use nystudio107\seomatic\models\MetaLinkContainer;
use nystudio107\seomatic\models\MetaScriptContainer;
use nystudio107\seomatic\models\MetaTitleContainer;
use nystudio107\seomatic\models\MetaTagContainer;

...

        $result = ContainerHelper::getContainerArrays(
            [
                MetaTitleContainer::CONTAINER_TYPE,
                MetaTagContainer::CONTAINER_TYPE,
                MetaLinkContainer::CONTAINER_TYPE,
                MetaScriptContainer::CONTAINER_TYPE,
                MetaJsonLdContainer::CONTAINER_TYPE,
            ],
            $uri,
            $siteId,
            true
        );

You'll get an array of the container information back, and you can do whatever you like with it.


Have you tried using the {{ craft.request.url }} variable in your returnUrl setting?

Also you should be able to format it like so:

returnUrl: craft.request.url ~ "?success"

More details about the craft.request model can be found here: https://craftcms.com/docs/templating/craft.request


How to improve unexpectedly poor Craft performance?

This is a great resource on improving performance as it's a multi-pronged attack:

Native craft caching {% cache %} which you mentioned you have done
CDN and Browser caching
Varnish and other tools, including plugins like Cache Warmer

I concentrated on cache as this is usually where the bottleneck seems to happen in Craft. Apologies if you've addressed all these already!


This isn't really a job for the Element API plugin. You can accomplish what you want much easier by just creating a plain ol' Twig template (e.g. templates/updates.json) that pulls the three latest updated entries from each section, and returns the entries' dateUpdated values as JSON:

{% header "Content-Type: application/json" %}

{%- spaceless -%}

{% set sections = ['themes', 'videos', 'screensavers'] %}
{% set entries = [] %}
{% for section in sections %}
    {% set entry = craft.entries.section(section).order('dateUpdated desc').limit(1).first() %}
    {% set entries = entry ? entries|merge([entry]) : entries %}
{% endfor %}

{
  {%- for entry in entries -%}
    "{{ entry.section.handle }}":"{{ entry.dateUpdated }}"{% if not loop.last %},{% endif %}
  {%- endfor -%}
}

{%- endspaceless -%}

The above would render a JSON payload exactly like the one you have in your example.

If you really want to use Element API for some reason, you can get pretty close to what you want (but not quite). Here's why it's difficult to do, though:

For one, the transformer property function operates on a single entry at the time, which is a problem in terms of your desired payload.

Second, with Element API you don't have full control of the JSON format the plugin returns – so you'll never get the payload to look exactly like you want (the actual data will be wrapped in a data property).

Third and most importantly, an Element API endpoint requires a single query (or actually, a single ElementCriteriaModel) to pull your elements. Unfortunately, it isn't possible to tell an ElementCriteriaModel to return 1 entry from each section – notice that even in the template example above, there's actually three queries – one for each section (they're just wrapped in a for loop to keep the code small and DRY).

So basically, you'll need to "trick" Element API to return something similar to your example JSON.

First, since you can't use a single ElementCriteriaModel to query your 3 latest entries, you'll actually need three of those suckers. The Element API plugin gives you one, but you'll need to create the other two inside the transformer function – you just need to ensure that Element API actually runs that function, and only runs it once, by pulling a single entry (in other words; you'll need a limit => 1 for your endpoint's criteria). It makes sense to have the endpoint pull one of the three entries you need, so you'll avoid a redundant database query. Then, you'll have to pull the other two entries "manually". Finally, for the return value you can return an array similar to what you have in your example:

'updates.json' => [
    'elementType' => 'Entry',
    'paginate' => false,
    'criteria' => ['section' => 'themes', 'order' => 'dateUpdated desc', 'limit' => 1],
    'transformer' => function(EntryModel $entry) {

        $themesEntry = $entry;

        $videosEntry = craft()->elements->getCriteria(ElementType::Entry, [
            'section' => 'videos',
            'order' => 'dateUpdated desc',
            'limit' => 1
        ])->first();

        $screensaversEntry = craft()->elements->getCriteria(ElementType::Entry, [
            'section' => 'screensavers',
            'order' => 'dateUpdated desc',
            'limit' => 1
        ])->first();

        return [
            'themes' => date('Y-m-d', $themesEntry->dateUpdated->getTimestamp()),
            'videos' => date('Y-m-d', $videosEntry->dateUpdated->getTimestamp()),
            'screensavers' => date('Y-m-d', $screensaversEntry->dateUpdated->getTimestamp()),
        ];
    }
]

The above would return a JSON payload looking something like this:

{"data":[{"themes":"2016-02-23","videos":"2016-08-23","screensavers":"2016-07-16"}]}


Craft-Multi-Environment-Config redirects to dev url on admin login

If the environment that you are working in is behaving like the settings that you have set for another environment, it's likely that the settings from that other environment are the ones that are being read by Craft.

The most common situation where I've seen this take place is based on the way that the Craft multi-environment config matches patterns for each environment you are in.

Let's say you have three environments:

website.com
dev.website.com
localwebsite.dev

Unless you are overriding the CRAFT_ENVIRONMENT variable in your index.php file, you may have a situation the keys of the multi-environment settings array match the pattern of the URL from the environment you are in.

Here's an abbreviated example multi-env settings array:

array(
    '*' => array(
        'environmentVariables' => array(
            'siteUrl'  => 'website.com',
        ),
    ),
    'dev' => array(
        'environmentVariables' => array(
            'siteUrl'  => 'dev.website.com',
        ),
    ),
);

// The Barrel Strength Multi-env config checks for an
// additional local config here.  In our example, that
// would be for the environment `localwebsite.dev`

In this example, 2 of your 3 environments are going to trigger the configuration for your dev site, and none are going to trigger the configuration for your local setup.

Both dev.website.com and localwebsite.dev will trigger the settings in the dev configuration in the array as Craft takes the first configuration that matches the pattern in the URL, and the word dev will match both of those environment URLs.

As the other comments have noted on the primary post, this is really just guesswork until we see the specific config settings you are using. I've tried to approach my answer as one that at least applies to a similar situation to the issue described even if it turns out that it doesn't help resolve the immediate question.


I tried eager loading before, and I couldn't figure out how to do it.

https://docs.craftcms.com/v3/dev/eager-loading-elements.html

Now I just query it using SQL. I know it's a bit hacking, but it gets the job done. The DB structure of craft_content table hasn't change since Craft 2 (when I started using craft), so its unlikely that future updates will break your code.

$command = Craft::$app->getDB()->createCommand("SELECT `ct`.`id`, `cc`.`title` FROM `craft_tags` as `ct` left join `craft_content` as `cc` on `ct`.`id` = `cc`.`elementId`");
$tags = $command->queryAll();

This is only a quick fix, if anyone had a better idea, just ignore this answer.


If the methods you need to alter are part of an auto-instantiated Service in the PerForm plugin, you might consider using Yii 2 “Behaviors.”

From the docs:

  …to attach a behavior dynamically, call the yii\base\Component::attachBehavior() method of the component to which the behavior is being attached…

  Source

So, in a custom Craft module, you might put something like this, in your init method:

use perfectus\perform\PerForm;
use modules\mymodule\MyBehavior;

// ...

PerForm::$plugin->emailService->attachBehavior('myBehaviorHandle', new MyBehavior);

This gives you a chance to monkey-patch the service with your own functionality… but I can't speak to how inheritance works, or whether you'll be able to call parent::myPatchedMethod($args) (or, in Behavior-land, $this->owner->myPatchedMethod($args)) to ensure the least code is duplicated.

Overall, I agree with Indigo: The best way to ensure this will continue to work is to make a PR to the plugin that adds support for events at key moments, and shuttles the right kind of data around to accomplish what you want. This is the only way to ensure you have a stable event API.


How to get all (prepped) field values from an entry, indexed by field handle

I kept thinking this was in the Craft core.
Wasn't, so I made my own: https://gist.github.com/timkelty/933efd23264d79d91b7a

Has come in useful in plugin dev and some templating.


Restrict Sources on element select field

I am not expert in Craft CMS but this is how it works for me:

Depending on the element type, source is different.

Look at this link how Craft CMS implements this:

https://github.com/craftcms/cms/blob/60881865f1b680c5aa5d4ad8f56d9a1ce3e452b0/src/fields/BaseRelationField.php#L842

Now how assets implement inputsource function:

https://github.com/craftcms/cms/blob/f83815cf28e7ce91edd501fc55ffd10f915a808e/src/fields/Assets.php#L550

so the format of sources for asset is like:

['folder:uid in volumefolders table']

and you can easily limit user to select assets from volumes you want.


Newly added child entries not showing on listing/parent page straight away

This is a known issue – automatic cache busting currently doesn’t work when the descendantOf param is set to an actual element.

Unfortunately there’s no easy fix on Craft’s end, without a pretty drastic change to how cache busting works.

As a workaround, you can change your descendantOf param value to currentPage.id rather than just currentPage.


How to create a migration for the main Craft DB?

You're looking for the answer to a complicated problem. :)

What you're thinking of I would describe as "content migrations" or "content model syncing".

There is currently nothing in Craft out-of-the-box that will do what you're looking for, although we've got some ideas on how we'd like to approach the sharing/syncing of content between environments/installations in the long term.

If you need something before then, you'll have to write a plugin that rolls its own solution.


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


Referring to this page, you can try this:

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


How to setup the Craft Commerce store both front and back end

You might need a web developer to install Craft and Craft Commerce 'locally' (on your computer), using a testing domain such at craftcommercedemo.dev

Using the '.dev' TLD will allow you to unlock Craft Pro and Craft Commerce so that you can see and test all of the CraftCMS + Commerce features.

Both Craft and Craft Commerce come with a set of template files, allowing you to interact with the site in the same way a regular visitor would (from the front end).

As a starting point, check out XAMPP (if you use a PC) or MAMP (if you use a Mac)

The above facilitates local Apache web server, plus MySQL database which will allow you to run Craft on your computer in the same way as you would on a real web server.

If you need a developer, check out this list of Craft Professionals...

Hope that helps


Overriding BaseFrontEndController in Craft Commerce

The most easiest solution in Your case is to create a custom Controller that extends the default BaseFrontEndController to call that one. The issue for Dependency Injection is the following piece of code:

For example when you do

Craft::$container->set('craft\controllers\EntriesController', [
    'class' => 'prefix\namespace\controllers\FooController'
]);

You would overwrite the default EntriesController with your custom one and the function createControllerByID would do the following

if (is_subclass_of($className, 'yii\base\Controller')) {
    $controller = Yii::createObject($className, [$id, $this]);
    // $controller is now my custom prefix\namespace\controllers\FooController instead of the default

    // but the line below -> get_class($controller) === $className won't match
    return get_class($controller) === $className ? $controller : null;
}

Thus you'll receive an exception, it will work with most other classes/services/components that are created with Yii::createObject but not with Controllers. To change that behavior you would have to replace the createControllerByID in yii\base\Module

Just do as Brad Bell already said and create a custom controller.


Take a look here, it sounds like you are hitting the max_input_vars limit. Strange things happen when you do.

Matrix field input error from within the control panel


How to use select dropdown with entries/saveEntry for an entry field?

I ran into this a while ago and it drove me nuts. Try adding disabled and selected attributes to your initial option in the select. So in your case <option disabled selected>---</option>.


Craft 3 CMS Solo setting general Logo option

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


If Conditional for Lightswitch in Matrix Field

You're close! The way you have your conditional set up now will print Hero Image Markup if either of your conditionals fail. By checking if block.displayHeroVideo is 1 on a block type that doesn't have that field, Twig will still return 0. You should only check displayHeroVideo when you know you are inside of a heroVideo block.

{% for entry in entry.heroFeatured.limit(1) %}
    {% for block in entry.hero %}

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

            {% if block.displayHeroVideo == "1" %}

Hero Video Markup

            {% endif %}

        {% else %}

Hero Image Markup

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


Not really, and it'd be pretty difficult for PHP to truly emulate a cron service since, by nature, it requires something to execute it before it can run (in Craft's case, a browser request).

The closest thing in Craft would be its "Tasks" (completely undocumented).  Tasks are usually meant for things that might take a long time for PHP to complete and it's not critical that they happen right away.

But you can't schedule, them... if there is a task in a "pending" state in the craft_tasks table, the next request to the control panel is going to trigger it.

I suppose we could add something like a "runDate" property to tasks where you could be at least guaranteed they wouldn't run until the first control panel request was made after that given date.


How would I list all entries regardless of section or structure?

Actually your code should work just fine. But by default only 100 entries are fetched, maybe you need to increase the limit:

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

But if you just want to create a Sitemap, try Ben Croker's Sitemap-Plugin (I really like it)


You could do this multiple ways.

One you could create a category with each month and an input for your entries and assign that month to each category.  Then it would be a matter of calling that categories relatedTo param using each Month Category ID.

{% set monthIds = craft.categories.group('months').ids() %}

{% for monthId in monthIds %}

        {# group each months entries #}
        {% for item in craft.entries.section('sectionName').relatedTo({targetElement:monthId}) %}
            {# content for each entry. #}
        {% endfor %}

{% endfor %}

Two you could use your eventStart field.

{# 1 == January #}
{% set months  = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"] %}
{% for month in 1..12 %}

        {# group each months entries #}
        {% set idx = month - 1%}

{{ months[idx] }}

        {% for item in craft.entries.section('blog') if item.eventStart|date("n") == month %}
            {# content for each entry. #}

{{item.title}}

        {% endfor %}

{% endfor %}


How can I get Sprout Forms errors in current language using AJAX?

The AJAX POST url variable (postUrl) should be set from the form template with this Twig code:

<script type="text/javascript">
    var postUrl;
    if ('{{ craft.i18n.getCurrentLocale() }}' == '{{ craft.i18n.getPrimarySiteLocale() }}') {
        postUrl = '/';
    } else {
        postUrl = '/{{ craft.i18n.getCurrentLocale() }}/';
    }
</script>

Furthermore, an hidden field should be added in order to call the Sprout Forms' controller on submit:

<input type="hidden" name="action" value="sproutForms/entries/saveEntry">

This submits the form in the current locale, and returns errors in this same locale.


First, there isn't a single specific template that ElementIndexController's actionGetElements uses to return data.

It implements IElementType's getIndexHtml method which BaseElementType provides a default implementation of, but any ElementType (Entry, User, Asset, custom plugin ElementType, etc.) is free to implement that method with their own logic.

Second, it sounds like you want to hack core files in the craft/app folder, which I definitely wouldn't recommend.

You might be able to make the modifications you're looking for with something like the CP CSS and CP JS plugins.


List only those months that have entries

{% set date = (date()).modify('first day of january 00:00:00') %}
{% for month in 1..12 %}
    {% set endOfMonth = clone(date).modify('last day of this month') %}
        {% set exists= craft.entries
            .postDate(['and', '>=' ~ date.format('-.m-d H:i:s'), '<=' ~ endOfMonth.format('Y-m-d H:i:s') ])
            .exists()
        %}

    {% do date.modify('first day of next month') %}
{% endfor %}

loop all months and check if there are entries in this month or not


Is it possible to cache a faceted search form?

There're various ways of doing this. The simplest would be to just use the submitted slugs to generate a new cache key for each different search, like Jamie suggests. This is a very straightforward and readable solution, which in most cases would probably yield a "good enough" performance boost. You'd simply create a key based on the params that are used in your cached content, so something like (could be made a bit less verbose if you prefer):

{% set submittedTypesArray = craft.request.getParam('type') %}
{% set submittedTypesString = submittedTypesArray | join('-') %}

{% cache using key "restaurant-filter-type-" ~ submittedTypesString %}
    {% set typeList = craft.categories.group('restaurantType') %}

    {% for type in typeList %}

            <input type="checkbox" name="type[]" id="{{ type.slug }}" value="{{ type.slug }}"{% if type.slug in submittedTypesArray %} checked{% endif %}>
            {{ type.title }}

    {% endfor %}
{% endcache %}

The backdraw of this solution is that it generates one cache entry for every different combination of the types. If this is "good enough" depends on your project.

If you want to use the approach naboovalley describes in the linked answer, here is a rewrite for your usecase:

{% set typeCategories %}
    {% cache using key "restaurant-filter-type" %}
        {% set typeList = craft.categories.group('restaurantType') %}

        {% for type in typeList %}

                <input type="checkbox" name="type[]" id="{{ type.slug }}" value="{{ type.slug }}" data-type-{{ type.slug }}>
                {{ type.title }}

        {% endfor %}
    {% endcache %}
{% endset %}

{% set types = craft.request.getParam('type') %}
{% for type in types %}
    {% set typeCategories = typeCategories | replace('data-type-' ~ type, 'checked')  %}
{% endfor %}

{{ typeCategories }}

It would be possible to do this with several category groups inside one variable/cache entry, but you'd have to give them different data-names to make sure that you don't run into problems if two categories in different groups have the same slug.

I'm sure there's a wicked elegant way to do the replace without the for loop, I just couldn't wrap my head around it right now. ;)

And, just to add more options, if this was a really high traffic site (or the server that hosts the site is really crappy), I'd actually update the status of the checkboxes with javascript on the client, instead of doing it with Craft. Even though it would maybe annoy a user that has javascript turned off and has to check all the checkboxes for every search, nothing would break. And you can't beat the performance of doing something on the client instead of on the server.


Creating forms that save to the database & can be viewed in the admin

For now, you can create forms and create entries through the plugin Guest Entries.

In Guest Entries, entries are disabled by default.

Sprout also has a plugin for creating forms, that is currently in beta.

Is there anything specific you are looking for, or would you just like to be able to receive submissions from site users?

If you give some more information, we might be able to give you some better advice, but the Forms Market is still pretty thin.

Would you say those forms are always the same in the context of a site? You don't need a form builder for that (?), unless they are always changing and adding things. Even then, you can make a rudimentary form builder by using Matrix.

The notifications part has to be be added by a custom plugin. You can hook into the onSaveEntry hook, for example.

I built a notification plugin that does that, which sends of an e-mail and a sms to the site owner when entries are added through Guest Entries.

Subscribing to MailChimp is also fairly easy. You can have a look at the MailChimp Subscribe plugin as an example.


How to display a tree view of all assets?

Yoursort, my answer was based on the assumption that the AssetsService could be used in templates. Ofcourse, only the variables can be used.

I don't have time to dive into this (now), but I think your best bet is to get all images, use `asset.folder' for each asset and 'rebuild' the hierarchical list of folder and their assets. Again, use cache ;)


How can I load the templates from a module?

Answer from @robin-schambach

It's not possible the way you do it... or the way you are trying to do it
During site requests only templates from your template folder can be loaded
otherwise it would be a high security issue


Each block within your Matrix field already has an ID, which you can access via block.id within a for-loop on your Matrix field:

{% for block in entry.myMatrixField %}
    ID: {{ block.id }}
{% endfor %}

If you want to be able to query directly for a specific Matrix block, you can use the Low Blocks plugin, which provides a craft.lowBlocks.id() function for accessing a block by its ID:

{% block = craft.lowBlocks.id(123) %}


CP Gear Icon missing? Created new Super Admin account

'Admin' permission is set on the user level, whereas 'userGroup' permissions are set on the userGroup level. And as far as I know, 'admin' permission should trump any userGroup permissions. I'm not sure how you got locked out, unless you unchecked the 'Admin' checkbox on your user profile settings perhaps? Regardless, setting the 'admin' value to 1 in the craft_users table should be sufficient to restore privileges, without clearing out the other tables.

The only way to create other Admins is to check the 'Admin' checkbox on the user profile permissions tab. The next best thing is create a userGroup (called 'administrator' for example) with all of the permission boxes checked. Keep in mind however, that userGroup permissions need to be set explicitly, so if you create a new section, you may need to update the userGroup permissions to allow the new section.


Installing Craft 3 - Internal server error

I have had a similar issue when using MAMP on OSX. The "solution" was to switch MAMP to use Module mode (all hosts use the same PHP version) rather than FastCGI mode (where you can run different PHP versions per host).

I have no clue why, but switching it allows the installation to complete. I am then able to switch it back to Fast CGI mode and everything works (although the issue sometimes occurs when installing/updating plugins).


I got it. I added this function to the Event_ElementType

public function isLocalized()
{
    return true;
}

This adds a language selector to your event index.

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

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

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

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


Loop through entries taking far too long to finish

Something like this should work and be faster.

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'journalArticles';
$criteria->limit = 10;
$entries = $criteria->find();

$titles = array();
$copies = array();

foreach ($entries as $entry)
{
    $titles[] = $entry->title;
}

foreach (array_count_values($titles) as $val => $count)
{
    if ($count > 1)
    {
        $copies[] = $val;
    }
}

$this->returnJson($copies);


You can create a custom plugin to fetch the data. Pluginfactory.io is a good place to create your basic files/folders. Then you'll insert this function in your PluginVariable.

public function getData($table){
    return craft()->db->createCommand()
        ->select('*')
        ->from($table)
        ->where('some Conditions)
        ->queryAll();
}

and in your template

{% for entry in craft.pluginName.getData('xyz') %}
    {{ entry.someField }}
{% endfor %}

Note: this only works when the table prefix is the same as your craft tables. So before your from($table) Craft will automatically include a $tablePrefix (usually craft_) you can either name your custom tables craft_ as well or change the prefix before your query

$oldPrefix = craft()->db->tablePrefix;
craft()->db->tablePrefix = '';
// handle your queries
craft()->db->tablePrefix = $oldPrefix;


How do I list the tag groups that are actually in use?

You could use the group filter to group your tags by tag groups:

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

    {# Get all the tags related to our gallery entries and group them by tag group #}
    {% set allGalleryTags = craft.tags.relatedTo(entries)|group('group') %}

    {# Loop the tag groups #}
    {% for tagGroup, tagsInGroup in allGalleryTags %}

{{ tagGroup }}

                {# Loop the tags of this group #}
                {% for tag in tagsInGroup %}

{{ tag.name }}

                {% endfor %}

    {% endfor %}


There is a CDN plugin called Upper. You could do a feature request on there github.com/ostark/upper/issues . Or look at how they implement the CDNs in their plugins and make your own.


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

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

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

{{ block.header }}

{% endfor %}

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

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

{{ block.header }}

{% endif %}

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


The concept of localization has changed in Craft 3, there are not only locales anymore - now you have different sites and site groups.

Example without multisite - only different locals

You can get all available sites for an entry with

{% set supportedSites = entry.getSupportedSites %}

This will return you an array of all supported sites for the entry.

{% for siteForEntry in entry.getSupportedSites %}
    {# get the site #}
    {% set site = craft.app.getSites.getSiteById(siteForEntry.siteId) %}
    {# check if it's the current site #}
    {% if site.id == entry.siteId %}
        active site = {{ site.id }} {{ site.language }}
    {% else %}
        {# if it's not the current site, get the entry for this site #}
        {% set entryForOtherSite = craft.entries.id(entry.id).site(site).one() %}
        link to site with id {{ entryForOtherSite.siteId }} {{ site.language }} - {{ entryForOtherSite.title }}
    {% endif %}
{% endfor %}

When you take a look at your /admin/utilities/deprecation-errors you'll see many records because all your locale functions will do this

public function locale(string $value)
{
    Craft::$app->getDeprecator()->log('ElementQuery::locale()', 'The “locale” element query param has been deprecated. Use “site” or “siteId” instead.');
    $this->site($value);

    return $this;
}

They tell you: "This function is deprecated, use "site" instead"

Example with multisite - different sites and locales

If you are going to have multiple different sites with multiple locales you can manage each site in one group and insert all the locales for these sites in each group.

- Site group A
    - language A (siteId 1)
    - Language B (siteId 2)
- Site group B
    - Language A (siteId 3)
    - Language C (siteId 4)

For Example if the user is in site group A you want to show only language A and language B but not Language C even if the entry exists in all sites.
So you can grab the group of the current site and loop through all sites of the group.

{% set currentSite = craft.app.sites.currentSite %}
{% for siteInGroup in currentSite.getGroup.getSites() %}
    {% if siteInGroup.id == entry.siteId %}
        active site = {{ siteInGroup.id }}{{ siteInGroup.language }}
    {% else %}
        {% set entryForOtherSite = craft.entries.id(entry.id).site(siteInGroup).one() %}
        link to site {{ entryForOtherSite.siteId }} {{ siteInGroup.language }} - {{ entryForOtherSite.title }}
    {% endif %}
{% endfor %}


How to manage different templates for a structure

Your approach looks good to me. There are different ways you can make it happen:

If you set up your structure in the CP you can decide how many levels you want to allow for that structure. (By default the number of levels is not limited.) If you have entered at least one parent entry in your structure, you can assign child entries in two ways:

1 – When you create a new entry you can choose a parent for that entry.

2 – If you miss that step or you change your mind later, you can move your entries around in the structure entries list: Choose your structure under „Entries“, klick and hold the cross in front of the entry you want to move and then drag it to the desired location. (So it´s possible to move a child entry from one parent to another later on.)

As for the templates for this set up, you have different options as described here:
How to load a different template for parent page

Another possibly interesting solution would be „Entry types“.

If you find that your parent entries would also use different fields than your child entries it could make sense to define a second entry type for the children in that section (https://craftcms.com/docs/sections-and-entries). When you define the „child" entry type, you assign fields to that just like for the first (parent) entry type. If you now enter a new entry for the section you can choose between the entry types and then are presented with the different field sets.

Regarding the templates you can still use the first solution but now you could change the layouts based on entry types as well:
In your template for single entries you could something like this

{% if entry.type == "child" %}
    {% include "sectionTemplateFolder/_types/child" %}
{% else %}
    {% include "sectionTemplateFolder/_types/parent" %}
{% endif %}

(This example assumes that you have an actual entry type called „child“, replace the „child“ in the if statement with your desired name.)

An elegant solution how to change layouts between several entry types is given here:
https://craftcms.com/support/entry-type-templates

Whatever approach you take you do not need to structure your templates like your entries. Within the Craft templates folder, the templates can live where it makes the most sense to you. For the entry-type example it could be

sectionName (folder)

index.html (for listing)
_entry.html (for the single entries)
_types (folder)

child.html
parent.html

Hope this helps?


Pagination, display 'Next 20 Results' etc

Not sure about a load of math, but if you've got pageInfo setup like in the docs, should be something like this:

{% set totalPages = pageInfo.totalPages %}
{% set itemsPerPage = 20 %}
{% set currentPage = pageInfo.currentPage %}
{% set totalItems = pageInfo.total %}

{% set wholeItems = (totalPages - 1) * itemsPerPage %}
{% set remainderItems = totalItems - wholeItems %}

{% if currentPage == totalPages - 1 %}
    Next {{ remainderItems }} items.
{% else %}
    Next {{ itemsPerPage }} items.
{% endif %}


How to Template Grid for Entries that Switch from Horizontal to Vertical?

{% if loop.index is divisible by(2) %}stuff{% else %}other-stuff{% endif %}


Service Unavailable Craft isn’t installed yet.

If you're getting that message, then Craft can connect to the database with the credentials you've provided, but it can't find the info table, so it thinks it's not installed.

Maybe the tablePrefix config setting is set incorrectly in your .env file?


Getting server-side feedback when submitting forms with jQuery Form plugin

I myself am building a data locker using JavaScript to talk to Craft. How I have it set up is that the AJAX request is pointing to a template (which a request can be routed to without defining it in the Control Panel) that will load if there are errors. I can then redirect to a success template if I find no errors. Alternatively, you can set the location to redirect to like you did in your example. I'm returning JSON on both templates so that I can run client-side checks to see what I'm getting back.

So if I have errors, I check for those on my request url template and output the JSON if necessary. If I don't, I load my redirect template which either returns a success message or the data I'm looking to retrieve.

You can tell Craft that it's returning a JSON file by giving it a ".json" extension. Alternatively you can also set it manually with:

{% header "Content-Type: application/json" %}

Either way, this should get you what you're looking to achieve.


Sprout Forms - Use Case - Retrieve/Store form data into a custom db table

Generally speaking, as I may not understand everything you are trying to do, it may be easiest to just have a custom module watch the \barrelstrength\sproutforms\elements\Entry::EVENT_BEFORE_SAVE Event and store the data as a JSON blob wherever you'd like.

If you don't wish to store the data in the normal way Sprout Forms lets you disable saving data to the database, or enable it and set the default to off so you only need to turn it on for use cases where you may want it to store the data in the plugin itself.

As far as retrieving that data, that would be up to you as you're storing it in a way that Sprout Forms wouldn't understand unless you retrieve and re-populate a Form Entry Model at some point in your workflow.

For a more integrated solution, you may want to explore Sprout Forms Custom Integrations API.

Integrations will run after a Form Entry is submitted and validated so you can use the Sprout Forms form builder to build and validate forms (and use features like conditional fields) and then, once the form is submitted you can hand things off to your Custom Integration and send the data wherever you'd like (to a third-party API or just somewhere else in the same database as you describe).

Some of the default integrations give examples on how you can build an Integration to handle custom mappings where you give the admin user an option to map the form fields they create to wherever you want to send the data to, however, Integrations don't require a mapping. If you just want to send the whole payload to a custom endpoint, you can do so and configure the endpoint of your other application to know what to expect.


I believe that it is not possible looking at the Matrix Block Model Docs.

What I would usually do, instead of having the front end facing title as the Field Name, is keep the Field name solely for the back end.

An example be (for a front end form)

<label>{{ 'Is your pet ever aggressive to strangers?' | t }}</label>
{% for option in matrixBlock.aggressiveBehavior.options %}
<input type="radio" name="aggressiveBehavior" value="{{ option.value }}">{{ option.label }}
{% endfor %}


Have you seen this solution: http://craftcookbook.net/recipes/120?

Vote here for better image cropping in Craft: http://feedback.craftcms.com/forums/285221-feature-requests/suggestions/7302748-intelligent-cropping-for-flexible-images


Can I query based on a date field rather than the postdate?

This should work:

{% set year = '2016' %}

{% set eventEntries = craft.entries
    .section('events')
    .where(['>=','field_eventStartDate',year~'-01-01'])
    .andWhere(['<=','field_eventStartDate',year~'-12-31'])
    .orderBy('eventStartDate asc')
    .limit(12)
%}


You're close!

You select the author correctly with and assign it to the myEntry variable:

{% set myEntry = entry.authorTeamMember.first() %}

Now you just need to output the data from myEntry instead of entry.  i.e.

{% if entry.authorTeamMember|length %}
    {% set myEntry = entry.authorTeamMember.first() %}

    {{ myEntry.authorName }}
    {{ myEntry.authorDescription }}
{% else %}

No Author

{% endif %}


How to limit number of entries returned from a group filter?

The reason limit() isn't working is that is a method on the ElementCriteriaModel you get from craft.entries.

Because you're actually dealing with a standard array when you access catEntries, what you want instead is Twig's |slice(start, length) filter:

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

   // You'll only get four entries shown here

{% endfor %}


What does the Timezone in Settings -> General represent?

You set it to whatever timezone the content authors will be in, so for example, when they say an entry’s post date is at 10 AM, Craft knows which timezone that should refer to.


You can find the id in the database in the craft_assetfolders table. Creating a field with uploads restricted to a single folder does not create an asset folder. The asset folder only gets created when you actually have an asset in that folder, so before that point there is no id.


Create folder in asset volume via GraphQL

Currently, there’s no direct way of doing this. You can pass an existing folder ID but you can’t create folders on the fly.
However, you can create folders via an asset field (with dynamic path) attached to an entry type so there is an option that could work if you really need this done.
Create a section/entry type that has two fields, an Asset field with a dynamic path set to {folderPath} and a plain text one called folderPath.
It would then happen in three steps:

Mutate the Asset and get its ID back
Mutate an entry in your new entry type where you set the Asset field to your (just uploaded) asset ID and set folderPath to whatever path you need, save and get its id back. This would create a folder and move your asset to it.
Delete the entry you’ve just created via a mutation using its id.

I know it’s not straight forward but if you really need to make it work, this would do the trick.


Check what methods were used on element query

Most of the time, you can check if an ElementQuery parameter has been set by checking the corresponding property name: it will be null if the parameter hasn't been set, and have the previously set value otherwise.
Examples
This will output 6:
  {% set query = craft.entries().relatedTo(6) %}
  {{ dump(query.relatedTo) }}

This will output null:
  {% set query = craft.entries() %}
  {{ dump(query.relatedTo) }}


import _self throwing ElementCriteriaModel could not be converted to string

In short, those two have nothing to do with each other. What's more likely is that the error is being triggered by the imported script. It's possible that your stack trace is just giving you a red herring by pointing to the import itself.

In your Twig code:

import pulls in a macro (or macros).

_self just means "this template file".

"mcr_home" is just how you're referring to your imported macro(s).

In the error message:

An ElementCriteriaModel is simply a model representing a Craft content search.

"could not be converted to string" is telling you that the model cannot be read as a string.

Obviously there is no correlation there. Take a closer look at the macro(s) you are importing... I'm certain you will find an ElementCriteriaModel which is attempting to be used as a string.


upgrade issue Yii Framework from version 2.0.15.1 to 2.0.16.1

Not sure about the Yii message, though it may be irrelevant. The Twig message refers to an issue where Twig itself was upgraded (to 2.7.2) which broke Craft. The makers of Craft were able to publish an fix within 48 hours.

Update to the latest version of Craft, this has already been fixed.


What's the best way to build URLs for dynamic content collections?

You need that custom route. With the dynamic URI setting the "entry route" is generated dynamically on entry save, but it stores a single, fixed route only.

But you don't have to miss out on Live Preview when you leave the "entry route" enabled in addition to your custom route. Set up separate Live Preview URIs that you don't link to and if you prefer you can 404 the request for all non Live Preview visits.

{% if not craft.request.isLivePreview %}
    {% exit 404 %}
{% endif %}


You set the variable that your are passing in to your include to a string. And in your include you try to access it like an object.

The variable which you’re passing in to your include is set to a string 'businessIntelCategories'. And in your include you try access a object property dynamically using that string which doesn’t work.

Use this code instead.

{% set entriesGrouped = entries|group('{ object[categoryName].first().title }') %}

Here’s an attempt to explain the syntax.

First you should have a look at the Craft documentation for Dynamic Entry Titles. You see that you can dynamically generate titles with a normal Twig template {{ object.property }} or a special shortcut syntax {property}.

The group filter uses the same internal functionality to render the string that you pass in as a filter argument group('my twig template string'). The syntax has to be a bit different though, because group already adds one pair of curly braces for you.

So usually you echo the title property like so

{{ object.title }}

and in the context of the group filter you can do both of the following.

{% set entriesGrouped = entries|group('title') %}

{% set entriesGrouped = entries|group('{ object.title }') %}

The first syntax, which uses the shortcut syntax, is documented and fine for most cases. But you can’t use it if you need to do something a bit more advanced, like using a ternary operator or in your case access the object object differently.

So to wrap this up, the syntax for group('{ object[categoryName].first().title }') is confusing. But what it does is to render the following Twig code for each element of your array of entries (each entry is passed in as the variable object).

{{ object[categoryName].first().title }}

If you don’t like the object['propertyName'] syntax, you can use the attribute function instead.

{{ attribute(object, categoryName).first().title }}


How do you determine if the current field is required from a fieldtype class?

In Craft 1/2, there isn't a particularly clean or easy way to do this because $this->model->required is only set in the context of when it's being called from a field layout.

In the context of a field type, Craft doesn't set it because required is a concept that belongs to a field layout and a given field can belong to multiple field layouts.

This whole process has been refactored and is much cleaner in Craft 3 so that $this->model->required works in the context of a field type where you'd expect it to.


Trying to build params to be able find entries related to an entry and that are related to a specific category

I think the answer you’re looking for is here.

TL;DR:

  relatedTo method accepts a CategoryModel, not the title(slug) of a category.


How do I check if a Global field exists in a template?

That's a known issue with Twig's is defined test.  See here for an explanation and workarounds.

Note that this is no longer an issue in the upcoming Craft 3.


Prevent EVENT_BEFORE_VALIDATE in specific case

First, you should test the sender property pointing to the User element.

Second, there's no such property as isNew in that case.

However, you could test that user is new given that its ID won't be set in case the user has not been saved yet.

Something like:

Event::on(
    User::class, // \craft\elements\User
    User::EVENT_BEFORE_VALIDATE,
    function (\yii\base\ModelEvent $event) {
        $sender = $event->sender;
        Craft::debug("User " . ($sender->id ? "already exists" : "is new"), __METHOD__);
    }
);


Rich Text - Redactor doesn't allow iframe even when in allowedTags config setting

If you can, update to the latest Craft build. There was a Redactor update in Craft 2.4.2682 back in July that updated Redactor and fixed issues with iFrames.


hi! can you recommend a good basic tutorial for Craft?

Both of these sites are run by Ryan Irelan

https://mijingo.com/craft

https://craftquest.io/


How cumbersome is the content admin with 6 different languages

Have a look at the video about the localization feature on the Craft Feature page, this should give you a really good impression on how it works.

There's one thing though, that I'd really like to see improved: a way to see which content is still the same across all locales and a way to keep content of a field in sync after the first entry save. See this feature request: http://feedback.buildwithcraft.com/forums/285221-feature-requests/suggestions/7187381-better-options-to-sync-content-across-locales.

Altogether I really, really like how localization is done in Craft, it's actually the feature that made me aware of it (I had lots of trouble with Wordpress mulitsite etc.). And I'm also rather sure that we will see some nice improvement to it over time (Craft is still a new CMS).


How do I iterate over a categories field in an entry

Try this approach:

<?php
return [
    'transformer' => function(craft\base\Element $entry) {
        $level1Categories = [];
        $level2Categories = [];
        $level3Categories = [];

        foreach ($entry->equipmentCategory->level(1)->all() as $category) {
            /** @var $category \craft\elements\Category */
            $level1Categories[] = $category->title;
            $children           = $category->getChildren()->level(2)->all();

            foreach ($children as $child) {
                /** @var $child \craft\elements\Category */
                $crumb      = [
                    $category->title,
                    $child->title,
                ];

                $level2Categories[] = implode(' > ', $crumb);

                foreach ($child->getChildren()->level(3)->all() as $subChild) {
                    /** @var $subChild \craft\elements\Category */
                    $crumb      = [
                        $category->title,
                        $child->title,
                        $subChild->title
                    ];

                    $level3Categories[] = implode(' > ', $crumb);
                }
            }
        }

        return [
            'entryTitle'   => $entry->title,
            'id'           => $entry->id,
            'url'          => $entry->url,
            'title'        => $entry->equipmentFriendlyName,
            'manufacturer' => $entry->equipmentManufacturer,
            'modelNumber'  => $entry->equipmentModelNumber,
            'description'  => $entry->equipmentDescription,
            'thumbnail'    => !empty($entry->equipmentImages->one()) ? (string)('https://acsweb.com' . $entry->equipmentImages->one()->getUrl()) : '',
            'categories'   => [
                'lvl0' => $level1Categories,
                'lvl1' => $level2Categories,
                'lvl2' => $level3Categories,

            ],
        ];
    },
];```


Localization - "not found" in CP on language selection

This turned out to be an issue with stalled tasks. There were a number of stalled tasks that were blocking the queue, preventing the localized pages from being created ("resave all localizable elements"). Clearing the stalled tasks resolved the issue. Thanks to Brad Bell for resolving this.


How do variables, services and models fit together?

For starters, I believe the Cocktail Recipes plugin is grossly out of date. It was originally built when Craft was in beta, and hasn't really been updated much since. There's a rumor that someone has forked & updated it, but I don't have the full story there.

Regarding your actual question...

Models - Think of a Model as a "jar" of related data, about one specific thing. This parallels pretty closely to most other programming languages and design patterns. As for Craft specifically, the Model is really the right way to pass a related group of data between components (Controllers, Services, etc).

Variables - A plugin Variable is simply a way to make your data easily available to front-end Twig templates. A large majority of the time, a Variable is simply a wrapper for some other method (like a Service call).

Services - Services can be anything and everything. It's a complete blank slate, and really the best place for your plugin to do any heavy lifting. If you ever have to interact with the database directly (via Records), it's virtually required that you run that DB interaction through a Service method.

Here are two resources which may help shed a little more light on how it all ties together...

Check out the Business Logic plugin template... Originally intended as a quick way to insert business logic into your site via PHP, it's become a useful learning resource as well. It focuses mainly on Variables, Services, and Controllers, and is completely documented in the code comments.

Lastly, here's a diagram which I put together as I was learning plugin development. Keep in mind, this is not a 100% 1:1 representation of every-plugin-ever. Any given plugin can contain more or less of these components... this is simply a basic illustration of how the components tie together.


Sounds like a plugin is your best option. Creating a model is simple, but if you want to use ElementCriteriaModel, you need to create a custom entity, which gets a little more complex. Check out https://github.com/pixelandtonic/Events for a great example on setting up custom elements.

If you were to just stick with a model, you could run queries to fetch models using BaseRecord and avoid writing queries.

Check out a these files from a plugin I wrote. I am storing API keys in a table with two custom columns, 'service' and 'api_key'.

Model (https://github.com/aberkie/transit/blob/master/models/Transit_KeyModel.php):

<?php

namespace Craft;

class Transit_KeyModel extends BaseModel
{
    protected function defineAttributes()
    {
        return array(
            'service' => AttributeType::String,
            'api_key' => AttributeType::String
        );
    }
}

Record (https://github.com/aberkie/transit/blob/master/records/Transit_KeyRecord.php):

<?php

namespace Craft;

class Transit_KeyRecord extends BaseRecord
{
    public function getTableName()
    {
        return 'transit_keys';
    }

    protected function defineAttributes()
    {
        return array(
            'service' => AttributeType::String,
            'api_key' => AttributeType::String
        );
    }

    public function create()
    {
        $class = get_class($this);
        $record = new $class();

        return $record;
    }
}

It is best to use Services to use the records to get the data and populate the models for use.
Service (https://github.com/aberkie/transit/blob/master/services/Transit_KeyService.php):

<?php

namespace Craft;
class Transit_KeyService extends BaseApplicationComponent
{
    protected $keyRecord;
    public function __construct($keyRecord = null)
    {
        if(is_null($this->keyRecord))
        {
            $this->keyRecord = Transit_KeyRecord::model();
        }
    }

    public function getKey($service = null)
    {
        if($service === null)
        {
            $records = $this->keyRecord->findAll();

            return Transit_KeyModel::populateModels($records);
        } else {

            $condition = "service = '$service'";
            $records = $this->keyRecord->find($condition);

            $model = Transit_KeyModel::populateModel($records);

            return $model->api_key;
        }
    }
}

You can use Yii's find function on records to limit results and use populateModels to return models.

$condition = "service = '$service'";
$records = $this->keyRecord->find($condition);
$model = Transit_KeyModel::populateModel($records);

If you didn't want to get this fancy, you could even just write your own mysql queries in your service files using craft()->db->createCommand()

$query = craft()->db->createCommand()
->select('*')
->from('myTable')
->where("myTable.name = '$name'")
->order("myTable.name")
->queryAll();

Hope this helps! Long answer short...look into making a plugin!


I often read the first user request is slowest to Craft Sites point mentioned in articles/posts, what exactly is that referring to?

Probably missing some context surrounding where you originally read that, but if it was talking about caching, then maybe it was referring to the first user that triggers the request to generate the necessary cached content.

  Is this loop that creates these URL's running every single time a page is requested? Is this bad practice?

Craft will process registerSiteRoutes on every request, so if you have a lot of business logic going on in your plugins around that method, it might be worth caching the results for a time to speed things up.

  Or do these files get loaded up regardless of being called, and therefore should be re-written into functions so that they don't load the data unless asked?

You assume correctly, but generally I'd recommend against haven't expensive operations in class constructors/init() methods.  My personal preference would be to explicitly load the data.

  Plugin count -- does having many small, niche plugins affect load speed versus less but larger plugins that cover more functionality? Is plugin count something that needs to be carefully considered, a common caution when working with a plugin-based CMS like Wordpress?

The more plugins, the more file system access Craft has to do to find and load them. That part is usually negligible performance wise, but there's nothing stopping a plugin from doing something crazy slow in its constructor/init() methods.

This has been alleviated in Craft 3 to a large extent, because Craft doesn't have to instantiate a plugin just to figure out information about it (version number, author, etc.).

  Basically, I guess the question is, I would love to be able to read a detailed explanation of the scheme/process in how plugins and their respective plugin file, config, services, controllers, templates, variables etc are loaded, and if there is a guideline on what is and isn't good practice when designing the flow of plugins for optimization?

Generally speaking, Craft will lazy-load a plugin's Controller, Enum, Helper, Model, Record, Service, Variable, and Validator classes as they are requested, just like Craft's own files are lazy loaded.


Allowing the user to update a CraftCMS pagination limit with listing filter options

You could create a form/a link with the limit and add the parameter in your $_GET request or as a segment to your url. This is just an example how to use it.

How many Entries would you like to get?
10
20
30

Then you can fetch this parameter

{% set limit = craft.request.getQuery('limit', 10) %}
{% paginate craft.entries.section(entry.slug).order('postDate desc').with: ['image'].limit(limit) as pageInfo, pageItems %}

Of course you have to attach this parameter to your paginate links as well

{% if pageInfo.prevUrl %}Previous Page{% endif %}

There are definitely better solutions but they require more time and more effort and a plugin/php but this would be the easiest solution


Invalidate cache from two channel expiry dates

the error was with the date format in the date comparison conditional and the until tag instead of unless

{% if currentTime <= newsDate | date('c') %} {# those two dates were formated differentely #}
    {% set invalidate = newsDate.expiryDate | date('c') %}
{% else %}
    {% set invalidate = auffuehrung.konzertStartdate |date('c') %}
{% endif %}

{% cache until invalidate %} {# not unless #}
 {# blablabla #}
{% endcache %}


Updating Craft 3 from ver. 3.0.28 10/23/2018

You need to manually update to the latest version of Craft 3.0.x, then update to Craft 3.1.x:

In your composer.json, change your Craft package to "craftcms/cms": "3.0.40",
Run composer update
Then in your composer.json, change your Craft package to "craftcms/cms": "^3.0.40",
Run composer update again


What's the most user friendly way to create a video block in a matrix field?

From basic to robust:

Redactor has a plugin along that same vein but it's more basic—feed it a URL and it spits out the embed code in a Redactor field.

Craft-video-embed-utilty sounds like it might work as a basic option here. It's not a field type but a Twig filter that'll take the video URL the user enters (you could use it with any field, including a plain text field) and then spit out the necessary Twig embed code. If you want to build your own "options" from scratch, this could work.

Embedded Assets allows you to use embeddable media such as YouTube videos to your assets manager and spit out the embed code necessary.

Dukt's premium Videos plugin is probably the most robust option. It'll actually connect to YouTube or Vimeo, hooks into Craft's interface, and visually allow you to search for and embed videos. It includes a videos field type that matrix compatible.


Modify Craft locale inside Element API plugin?

Craft::t() has a whole bunch of parameters you can pass into it.

public static function t($message, $variables = array(), $source = null, $language = null, $category = 'craft')

It sounds like what you're looking for is the 4th one.

Craft::t('my string', null, null, 'es')

Where 'es' would be a target locale other than your main one.


Where do you set PEM file passphrase for Craft CMS Push Notification Plugin for an iOS app?

From my research and testing, it looks like this plugin doesn't offer the option to set a passphrase for the PEM file. I had to create a new PEM file that doesn't require a passphrase in order to send a successful alert.


This sounds like a problem with your email configuration, not the form plugin.

Check your site wide email settings, specifically check the "Protocol". If you are using "PHP Mail", you're gonna have a lot of problems. The best option is "SMTP".

There are several SMTP services to choose from. We've been using Mailgun for several years, and are very happy with them.


Would be a lot cleaner/more efficient to do this from a custom plugin in PHP, but if you want to do it from a template, this should work:

{% set entryArr = {} %}

{# Grab all of the entries in the section #}
{% set entries = craft.entries.section('news').find() %}

{# Loop through them generating a random number between 0 and the weight custom field #}
{% for entry in entries %}
    {% set entryArr = entryArr|merge({(entry.slug): random(range(0, entry.weight))}) %}
{% endfor %}

{# Sort the array by the ascending value maintaining the keys #}
{% set entryArr = entryArr|sort %}

{# print them off #}
<ul>
{% for slug, randomNumber in entryArr %}
    {% set entry = craft.entries.slug(slug).first() %}
    <li>{{ entry.title }} - Max Range: {{ entry.randomNumber }} - Random Number: {{ randomNumber }}
{% endfor %}
</ul>


Craft 2 FormBuilder 2 equivalent plugin in Craft 3

There are a large number of form plugins in the Craft plugin store. See: https://plugins.craftcms.com/categories/forms

Some options:

Solspace Freeform
Solspace Express Forms
Sprout Forms


Craft uses MySQL's native mysqldump and PostgreSQL's pg_dump binaries to create database backups.

In order for PHP to be able to execute those binaries, it needs to be able to run the proc_open and proc_close PHP commands.

I would not consider it a security issue, but if you were really concerned about it, you can prevent Craft from making backups on update and/or specify your own backup logic bypassing Craft's default implementation.


That will give you all entries, from today (so not past entries) starting after 5PM:

{% set startAfterTime = '17.00'|date('U') %}
{% set today = now|atom|date %}

{% set events = craft.entries()
    .section('events')
    .status(['live', 'pending'])
    .postDate('>=' ~ today )
    .eventStartTime('>=' ~ startAfterTime)
    .all() %}


Images containing EXIF orientation tag are not rotated on upload

After some mail exchanges with Brad and Andris from Craft CMS, it turned out that there is an edge case where the image rotation on upload will not work if the EXIF extension is not installed (which was our case).

There are two solutions to fix this problem:

Install EXIF extension
Install and use Imagick instead of GD.

As Imagick is the recommended image extension for Craft, we ended up installing Imagick on the server.

This is already working with Imagick on Craft 3, and will soon be working on Craft 2 with the next update (> v2.6.2954).


What's the correct syntax for recipients in Sprout Email?

This should work:
{{ object.userBooking.first().email }}

I would check if the problem is with something else.


How do I query multiple element types in one query

This is more of a limitation of Craft than Commerce, but it's currently not possible in one query... you'd need to do two and perform some merging/filtering logic.

Consider thumbs-upping/commenting on this feature request which would enable what you're looking for.


Where are the links coming from? A Template?

"?p=1504" should not 404, if it's attached to the end of an existing "200" url.

Do a crawl with an app called "Screaming Frog" to determine where your 404s are actually coming from then you can fix in your templates.

Sounds like your just sweeping the actual problem under the carpet and not fixing the source of the problem!


Get entries by month, but not restricted by year

I think a better way would be to add a Preparse field to your Course Dates’ field layout that stores only the month.

https://github.com/aelvan/Preparse-Field-Craft

The code for the preparsedMonth field.

{{ entry.courseStartDate|date('m') }}

With that in place you can drastically simplify your template code and reduce database queries.

{% set categoryParam = craft.request.getParam('month') %}

{% set allDates = craft.entries({
    section: 'courseDates',
    courseStartDate: '>= ' ~ now|date('c'),
    preparsedMonth: categoryParam ? '%02d'|format(categoryParam) : null,
    order: 'courseStartDate',
    limit: null,
}) %}


Guest entries - send confirmation mail to person who filled out entry

Assuming the person that applied has a text field they entered their email address on in the Guest Entry, then the plugin has an onSuccess event that gets fired when a guest entry is successfully saved.

You could listen to that from another plugin, grab their email address from the custom field, then build an email and programatically send it their way.


This can also be done with a Twig macro, rather than creating a plugin:

{% macro ordinal(number) %}
    {%- spaceless %}
    {% if ((number % 100) >= 11) and ((number % 100) <= 13) %}
        {{ number }}th
    {% else %}
        {% set ends = ['th','st','nd','rd','th','th','th','th','th','th'] %}
        {{ number ~ ends[number % 10] }}
    {% endif %}
    {% endspaceless -%}
{% endmacro %}

{% from _self import ordinal %}

{% for entry in craft.entries %}
    <li>{{ ordinal(loop.index) }}</li>
{% endfor %}


Performance hit from Entry Url Format with multiple {% if %} clauses?

As far as Craft is concerned whatever is in the Entry URL Format field is just another Twig snippet of code.  It gets rendered down super fast just like any other Twig code.  A few if conditionals aren't going to have any measurable impact on that process.


Return entries where field is "not empty"

1. "Expected name or number" error

The parser is expecting a method/property after the dot of productSale, but you are passing arguments. Removing the dot to make it valid:

{% set products = craft.entries.section('product').productSale(':notempty:') %}

.

2. Documentation

There is no documentation on this yet, but it is listed in the release notes:

  Added support for passing “:empty:” and “:notempty:” to
  ElementCriteriaModel parameters when you’re looking for
  empty/non-empty values.


Programatically Adding Fields to a Layout

While I am adding them from a plugin, I ran into a similar issue as you, and like you, I didn't like the "recreate the layout from scratch" method the linked answer used. I know this question is old, but it seems the most apt place to put my solution to this issue and contribute to more code samples.

After some experimenting, I got a solution that works (whether it's "the Craft way," I'm not totally sure, and I'm sure some of it could be cleaned up, but it's not like there's a lot of documentation on that front, as we've both found).

This code creates the fields, a field group, and a tab, then adds the tab and fields to the User Layout:

    // Create the field group
    $groupModel = new FieldGroupModel();
    $groupModel->name = 'CustomGroupName';
    craft()->fields->saveGroup($groupModel);

    // I haven't yet found a way to get the group ID without looping through all of the groups. saveGroup() returns a boolean and doesn't appear to update the id attribute of the original model instance.
    $groups = craft()->fields->getAllGroups();
    foreach($groups as $group) {
        if($group->name != 'CustomGroupName') {
            continue;
        }
        $groupModel = $group;
    }

    // Create the tab
    $tabModel = new FieldLayoutTabModel();
    // Get the desired layout (in this case, the User layout) and use the tab's setLayout to link the two
    $layout = craft()->fields->getLayoutByType(ElementType::User);
    $tabModel->setLayout($layout);
    $tabModel->name = 'CustomTabName';

    // Create the fields. I have a protected class member that contains the fields in a 'fieldName' => 'FieldName' format.
    foreach($this->fields as $field => $name) {
        $fieldModel = new FieldModel();
        $fieldModel->groupId = $groupModel->id;
        $fieldModel->name = Craft::t($name);
        $fieldModel->handle = $field;
        $fieldModel->translatable = false;
        $fieldModel->type = 'PlainText';

        craft()->fields->saveField($fieldModel);
    }

    // Get all of the group's fields. This could also be done by saving an array of the fields in the loop above, but this seems a bit cleaner to me, and since we already have the group object, saves us an object/variable declaration.
    $fields = $groupModel->getFields();

    // Set the tab's fields. This gives us a custom grouping in the layout editor.
    $tabModel->setFields($fields);

    // Get the existing tabs (and, by extension, fields), since we don't want to nuke the layout, just add to it. I couldn't find any sort of "addTab" type function, so this is how we have to do it.
    $layoutTabs = $layout->getTabs();

    // getTabs() returns an array, so simply add our new tab to the array.
    $layoutTabs[] = $tabModel;

    // Now, set the tabs back in the layout.
    $layout->setTabs($layoutTabs);

The reversal is exactly that--a reversal:

    $group = null;

    // Delete the fields
    foreach($this->fields as $field => $name) {
        $fieldModel = craft()->fields->getFieldByHandle($field);
        if($fieldModel) {
            // Grab the group from one of the fields. Presumably (in my case), they're all in the same group. This could be refined for a less ham-fisted approach. Unfortunately, it's either this, or doing the loop-through-all-groups method we did in the create section, that I've found.
            $group = $fieldModel->group;
            craft()->fields->deleteField($fieldModel);
        }
    }

    // Delete the field group
    if($group) {
        $groupModel = craft()->fields->getGroupById($group->id);
        // I made sure it was empty, since I don't want to delete the group if more fields were added.
        if($groupModel && empty($groupModel->getFields())) {
            craft()->fields->deleteGroupById($groupModel->id);
        }
    }

    // Delete the layout tab
    // Get the layout...
    $layout = craft()->fields->getLayoutByType(ElementType::User);

    // Get the tabs...
    $tabs = $layout->tabs;

    // Find and delete the tab we want, in the same fashion, except now we're unsetting the array instead of setting it.
    foreach($tabs as $index => $tab) {
        if($tab->name != "CustomTabName") {
            continue;
        }
        unset($tabs[$index]);
    }
    $layout->setTabs($tabs);


I finally got to the bottom of what happened. I deleted a user about a month ago and after 30 days (the soft delete period) Craft deleted all related pages that the user had originally created. Thankfully, I was able to restore those pages by re-creating records for each in the entries table with a different authorid.
I ran this script on a backup of the database to find the entries for that author.
select es.uri, c.title, et.*, e.* from entries e
inner join entrytypes et on e.typeid=et.id
inner join elements el on e.id = el.id
inner join elements_sites es on es.elementid = el.id
left outer join content c on c.elementid = el.id
where e.authorid=DELETED_USER_ID
and el.revisionid is null

And then created insert scripts for the entries table for each one I needed to restore. The elements and other data was still in the database so I just had to re-create the entries records.
insert into entries (id, sectionid, parentid, typeid, authorid, postDate, deletedWithEntryType, dateCreated, dateUpdated, uid)
VALUES(ORIGINAL_ENTRY_ID, ORIGINAL_SECTION_ID, ORIGINAL_PARENT_ID, ORIGINAL_TYPE_ID, NEW_AUTHOR_USER_ID, ORIGINAL_POST_DATE, 0, ORIGINAL_DATE_CREATED, ORIGINAL_DATE_UDPATE, ORIGINAL_UID)


There are two basic issues with using includes in this scenario, both of which you have discovered.

The first is that included templates do not have access to variables defined in master templates. You would have to specifically pass the variables to the template in the include statement using the with clause.

The second is that extended templates cannot have a body outside of a declaration block, and includes are by definition expected to return html, and thus throw an error.

A better solution would be to use hierarchical extensions vs includes, placing all shared content together in the parent template. All variables in child templates should bubble up through the template hierarchy and be available to the parent templates. Something like the following for example (I've left out much of the content for brevity).

In _layout.html:

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <html lang="en-gb" dir="ltr" class="no-js"> <!--<![endif]-->

<head>
    {# meta #}
    <meta charset="utf-8">
    <title>{% if metaTitle is defined %}{{ metaTitle }} - {% endif %}{{ siteName }}</title>

    {# set seo #}
    <meta name="description" content="{% if metaDescription is defined %}{{ metaDescription }}{% endif %}">
    <meta name="keywords" content="{% if metaKeywords is defined %}{{ metaKeywords }}{% endif %}">
    <link rel="canonical" href="{{ siteUrl }}">
    <meta name="robots" content="{% if metaRobots is defined %}{{ metaRobots }}{% else %}index,follow{% endif %}">

    {# set open graph #}
    <meta property="og:site_name" content="{{ siteName }}">
    <meta property="og:type" content="website">
    <meta property="og:title" content="{% if metaTitle is defined %}{{ metaTitle }} - {% endif %}{{ siteName }}">
    <meta property="og:url" content="{{ siteUrl }}">
    <meta property="og:image" content="{% if openGraphImage is defined %}{{ openGraphImage }}{% else %}{{ siteUrl }}images/og-default.jpg{% endif %}">
    <meta property="og:description" content="{% if metaDescription is defined %}{{ metaDescription }}{% endif %}">

    ...etc

    {# set default site meta variables, if any #}

    {% block head %}{% endblock %}

</head>

<body>

    {% block content %}{% endblock %}

    {% block footer %}{% endblock %}

</body>

</html>

In _home-layout.html:

{% extends "_layout" %}

{% block head %}
    {# additional home head content #}
{% endblock %}

{% block content %}{% endblock %}

{% block footer %}
    {# home footer content #}
{% endblock %}

In _page-layout.html:

{% extends "_layout" %}

{% block head %}
    {# additional page head content #}
{% endblock %}

{% block content %}{% endblock %}

{% block footer %}
    {# page footer content #}
{% endblock %}

In your index.html template:

{% extends "_home-layout" %}

{# set home meta variables, etc #}

{% block content %}
    {# home body content #}
{% endblock %}

In your page.html template:

{% extends "_page-layout" %}

{# set page meta variables, etc #}

{% block content %}
    {# page body content #}
{% endblock %}

In this way you can group shared content in the parent template and specific content further down the template hierarchy. How best to structure this hierarchy to keep you code 'dry' will be heavily dependent on the needs of your project so I won't even begin to guess.

Keep in mind it is also possible to define blocks of html in variables using conditionals and then place those variables into the block declarations.

{% if craft.request.firstSegment %}

    {% set footer %}
        {# page footer content #}
    {% endset %}

{% else %}

    {% set footer %}
        {# home footer content #}
    {% endset %}

{% endif %}

{% block footer %}
    {{ footer }}
{% endblock %}


If currentUser isn't defined, it returns null. So what's probably happening is you have people visiting the site who don't have user accounts or aren't signed in, which means the currentUser variable is set to null for them. So in your query you end up passing null to the authorId param, which means it will get everything (null being the default if I'm not mistaken). Most likely in your local environment you did all your testing while being signed in.

To solve, you'll want to surround your code in a conditional:

{% if currentUser %}
    {% set campaigns = craft.entries.section('campaigns').authorId(currentUser.id).all() %}
    {% set proposals = craft.entries.section('proposals').relatedTo(campaigns).all() %}
    {% set proposalsByGroup = proposals|group('proposalStatus') %}
{% else %}
    Please sign in to view your proposals...
{% endif %}


The way the plugin is currently written, it won't support your initial syntax. i.e. range('and', '>=' ~ result.points, '<=' ~ result.points).  It would need to override BaseFieldType's modifyElementsQuery to support that syntax.

You could slightly improve on your solution by using the MN Break and Continue plugin to at least break out of the for loop once a match is found.


Plugin Settings Color Input Javascript Event Listeners

If this is your plugin, you can register an AssetBundle with custom CSS and JS for your plugin. This will be loaded in your plugin settings page, and in your JS file you can then specify an event handler for your colour picker. You might need to add a specific class to the input in the settings template to ensure you can select it easily in your JS file.
If this is referring to a first/third-party plugin, you could use a plugin like CP JS to load a custom JS file into the CP and attach an event handler in that file to trigger your XHR.


Nevermind, I did not understand that Mollie is an off-site implementation. So the checkout just redirects you to the Mollie environment. If you want to implement on-site payments using Mollie you'd have to write your own logic I presume.


95% of the time you see a 400 Bad Request error, it's because it's a CSRF token validation error (or you're just missing the token all-together).

Craft 3 has CSRF validation enabled by default.

Here's how to pass the CSRF token to your JS in Craft 2: https://craftcms.com/support/csrf-protection#updating-your-javascript

Here's the CSRF token changes in Craft 3 you'll need to change: https://docs.craftcms.com/v3/changes-in-craft-3.html#csrf-token-params


Matrix field breaks backend Entries > 'page-name' page. "Endless" recursion error?

Brad was right, it was xDebug that was the culprit. So here's what I did:

In the Linux terminal I ran:

sudo gedit /etc/php5/mods-available/xdebug.ini

In the xdebug.ini file I added the line below and saved.

xdebug.max_nesting_level=256

In the Linux terminal I ran:

sudo service apache2 restart

Done.

Note: if the this does not fix it, try changing the command in step 1 to:

sudo gedit /etc/php5/conf.d/xdebug.ini

or just edit your php.ini file where ever it may be located.


Craft 3: Can't backup database ("mysqldump: command not found")

Craft 3 did away with the PHP-based database backup solution that Craft 2 utilized (for many reasons).

Now it requires that the mysqldump executable (if you're using MySQL) or pg_dump executable (if you're using PostgreSQL) is available to PHP in order to do backups.  This is usually just a matter of including the path to that executing in your PATH environment variable.

There is also the backupCommand config setting that you can use to override Craft's default backup implementation if you have some other backup solution you'd like to use.

Same for restoreCommand.

Related issue here: https://github.com/craftcms/cms/issues/1369


Sounds like a feature request for the developers of Venti, but this code should help you achieve what you need.

{% set upcomingEvents = [] %}
{% set upcomingEventIds = [] %}

{% for event in events %}
    {% if not event.eid in upcomingEventIds %}
        {% set upcomingEvents = upcomingEvents|merge([event]) %}
        {% set upcomingEventIds = upcomingEventIds|merge([event.eid]) %}
    {% endif %}
{% endfor %}


My guess is that one of the orders in the array of orders has a null billingAddress, and the dump you did was for just one of the orders.

If you are going to access the address firstName through the order's billing address, but the address might be null you need to do a check.

You can either do:

{% if order.billingAddress %}
 {{ order.billingAddress.firstName }}
{% endif %}

Or use the null-coalescing operator in twig:

{{ order.billingAddress.firstName ?? '' }}

https://twig.symfony.com/doc/2.x/templates.html#other-operators

Hope that helps.


Response: {"error":"Undefined index: fieldGroup"}

You can rebuild your project.yaml by running ./craft project-config/rebuild.

In terms of workflow here's a good article that discusses it.


You can listen to the add button's click event like so:

$('.matrix > .buttons > .add').on('click', function(e) {
    // your js
});


Answer is provided in the original post and this can be assumed solved.


FastCGI error when accessing a local development site using MAMP Pro

Following the answer in this issue https://stackoverflow.com/questions/15563217/apache2-fastcgi-comm-with-dynamic-server-aborted-first-read-idle-timeout/15565267#15565267 I was able to successfully run my script without this dreaded timeout and 500 error, like so:

Go to File > Edit Template > Apache > httpd.conf
Do a Find & Replace for MAMP_FastCgiServer_MAMP
Comment out the line MAMP_FastCgiServer_MAMP
Add a config line for your version of PHP, with the desired timeout limit at the end like so: FastCgiServer /Applications/MAMP/fcgi-bin/php5.6.2.fcgi -idle-timeout 3600

For your version of PHP the code block would look like this, with the two changes being the second and third last lines:

<IfModule mod_fastcgi.c>
    # URIs that begin with /fcgi-bin/, are found in /var/www/fcgi-bin/
    Alias /fcgi-bin/ "/Applications/MAMP/fcgi-bin/"

    # Anything in here is handled as a "dynamic" server if not defined as "static" or "external"
    <Directory "/Applications/MAMP/fcgi-bin/">
        SetHandler fastcgi-script
        Options +ExecCGI
    </Directory>

    # Anything with one of these extensions is handled as a "dynamic" server if not defined as
    # "static" or "external". Note: "dynamic" servers require ExecCGI to be on in their directory.
    AddHandler fastcgi-script .fcgi .fpl

    MAMP_ActionPhpCgi_MAMP

    #MAMP_FastCgiServer_MAMP
    FastCgiServer /Applications/MAMP/fcgi-bin/php5.5.10.fcgi -idle-timeout 3600
</IfModule>

Also reference this solution:  https://stackoverflow.com/questions/24715426/how-do-you-increase-the-apache-fastcgi-timeout-on-mamp-mamp-pro/24976009#24976009


Routing: ignoring a segment from the URL

I did something similar for a site that showcased projects.

In the top of my entry page, I had code like this:

{% set entrySlug = craft.app.request.getSegment(2) %}
{% set entry = craft.entries.section('services').slug(entrySlug).one() %}

{% if entry is not defined or entry is null %}
    {% exit 404 %}
{% endit %}

And then I've got two routes:

services/<slug>/* which routes to services/_entry

services/<slug> which routes to services/_entry

Might not need both, but for me, when I didn't have both, I'd get a 500 error when the second segment was broken.


Custom element type defineSearchableAttributes

Craft will only extract the search keywords for an element during the element saving process.

If you have existing custom elements already saved, then you go in and add the defineSearchableAttributes() to your element type, you'll need to re-save the existing elements in order for their search keywords to be indexed.

Or now that I think about it... the easier way would probably be to just run the "Update Search Indexes" tool in the Control Panel under Settings->Tools. It will do the same thing for you.


I am by no means a caching expert, but here's what I do know...

When you wrap a chunk of Twig code in a cache tag, it processes that chunk of code all the way down to HTML, then stores that HTML in the database. A cache key references this pre-parsed HTML code, so it can be easily called up later.

But in addition to the HTML itself, two other pieces of data are stored alongside it:

A list of criteria used to generate the HTML
A list of elements used to generate the HTML

The main reason that criteria and elements are also recorded is for the purpose of cache invalidation... So for example, if someone were to change an element associated with a cached chunk, that chunk would immediately become invalidated. You wouldn't need to write a separate plugin in that case, the cache would be invalidated simply by updating a corresponding element. Something similar happens to criteria, if the criteria results would have changed.

Check out this question which I asked awhile ago... It goes into greater depth about the related caching tables, and how they work together to make sure your cache stays fresh.

Also, make sure you've reviewed the official recommendations about the proper usage of cache tags, to figure out the best times to use (and not to use) the tag.

Lastly, I'd recommend taking the time to watch this excellent video from Barrel Strength Design about the wonders of the cache tag. There is a lot to be learned from that video, and it's a great way to get your bearings on caching in general.


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

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


Craft Commerce not sending E-Mails immediately

Thanks to @PhilipBoomy for his answer.  The problem were missing cron jobs.

Additionally I want to add one more solution from the craft support team:

If you don't have the queue set up to run automatically with a cron job or worker, you can also try adding this to your order confirmation template:

{# run queue #}
{% do craft.app.queue.handleResponse %}
{{ craft.app.response.content|raw }}

Which will run the queue over Ajax on that page.


I just saw this. Consider this plug-in:
https://github.com/born05/craft-assetusage


How can I include a Users picker in a custom field type?

I don't know your requirements, but you could build a "Users Picker" with the Dynamic Fields plugin. You would basically need to do the same in its settings to build your select options as you'd do in a custom plugin.

You get your users with craft.users and then build an array with "label" and "value" keys using the merge filter.

Pass that array into the Dynamic Fields' settings or build the select options with the forms.selectField macro in your own plugin.

{% set users = craft.users.group('clients') %}

{% set userOptions = [] %}
{% for user in users %}
    {% set userOptions = userOptions|merge([{ label: user.friendlyName, value: user.id }]) %}
{% endfor %}

{{ forms.selectField({
    label: 'User'|t,
    id: id,
    name: name,
    options: userOptions,
    value: value ? value
}) }}


Can you pass a variable with includeJsFile?

You can't pass a JS variable into a JS file (that doesn't quite make sense). What you can do is to create a JS variable, and make it accessible to the script you are including.

So you'd include your JS file as you are already doing:

{% includeJsFile 'path/to/file' %}

And then you would create your variable, and in JavaScript pass that variable back into the script which you called.

{% includejs %}
    var myData = 'whatever your data needs to be';
    functionFromIncludedScript(myData);
{% endincludejs %}

The snag you're going to run into here is, the order matters. When you use Craft's include methods, they will always include any files before any raw scripts. So using this method, your variable will be defined after the file has already been included.

  It's important to note, the "files before raw scripts" will happen regardless of which order you defined them in Twig.

Similarly, be aware that your file include and raw script include will both happen at the bottom of the page, just before the closing </body> tag.

Now I'm going to make an assumption... You're about to say "But I need my variable declared before the file is included!"

Fair enough, and the solution is pretty simple. Just declare your JS variable in the middle of the page, while you're rendering the main Twig code:

<script>
    var myData = 'whatever your data needs to be';
</script>

So your variable declaration gets rendered along with the rest of your HTML, and your includeJsFile still happens at the bottom of the page. By the time that file is included, your JS variable is sitting around waiting for it.


Paginate entries with offset / limit when templating

You could use Twig's Slice function.

{% set firstTwo = paginatedEntries|slice(0,2) %}
{% set lastFour = paginatedEntries|slice(2,4) %}

Then loop over firstTwo for your first items.

{% for entry in firtTwo %}
   {# Show first 2 entries #}
{% endfor %}

Loop over lastFour for your final items.

{% for entry in lastFour %}
   {# Show next 6 articles #}
{% endfor %}


{{ entry.postDate|date }} Variable "entry" does not exist

The entry variable is automatically created for the individual entry pages that you define in your section settings.
For example, if your Section has the following Site Settings:

URI Format: blog/{slug}
Template: blog/_entry

You can expect an entry variable to exist when the blog/_entry is loaded.
blog/_entry.twig
{{ entry.postDate|date('medium') }}

some-other-template.twig
If you are trying to access an entry in some other template, you would need to make sure you define the entry variable on the page.
{% set entry = craft.entries.id(123).one() %}
{{ entry.postDate|date('medium') }}

You don't need to query the entry by ID, it was just an easy example. You can use any element query options and read more about them in the Querying Entries section of the docs.
is defined
If you have a scenario where you don't know if the entry will exist or not, you can check for its existence using is defined:
{% if entry is defined %}
  {{ entry.postDate|date('medium') }}
{% endif %}

debugging
If you are curious what does exist, you can turn on the devMode setting in your config/general.php settings and dump the variable to see more about what the application is seeing:
{{ dump(entry) }}


Printmaker plugin cuts off HTML when rendering PDF link

Depending on your server setup, DOMPDF might be resetting the output buffer when the PDF is generated. This is a fairly rare issue, but I have heard of it before.

Solution: Try moving the Printmaker PDF-generation code to the top of the template before any output.

For example, at the top of the template...

{% set pdfUrl = craft.printmaker.pdfFromTemplate('support-guides/download', vars, settings).url %}

...and then later, in your output content...

Download PDF Support Guide


Is it safe to move Craft Commerce Templates out of Plugin

You can copy them into your templates folder if you want to use them as a starting point.

I've added a mention of that into the installation docs here: https://docs.craftcms.com/commerce/v2/installation.html#example-templates


First you create an asset source uploads. Then you create an asset field and set its upload location subfolder to {postDate|date('Y')}/{postDate|date('m')}

When you edit an entry, any files you upload will go in the subfolder for the year and date. If you have selected Restrict uploads to a single folder? in the asset field, then only assets in that subfolder can be used.


Writing a plugin would be your best shot. You can use AssetsService to get all the information you need (http://buildwithcraft.com/classreference/services/AssetsService)

This might change with a future release, but the need to query Assets folders directly from a template is so rare, that I'm not entirely convinced it will make it's way into a future release at this point.


Matrix entry causing last bootstrap column to be shunted down

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 %}


Order Entries Query by a Featured Light Switch

You're looking for the filter filter. Here's how you might do it:
{% set entriesInCat = craft.entries.relatedTo(category).all() %}
{% set featuredEntriesInCat = entriesInCat|filter(entry => entry.yourLightswitchFieldHandle) %}
{% set remainder = entriesInCat|without(featuredEntriesInCat) %}

{% for item in featuredEntriesInCat %}

{{ item.title }}

{% endfor %}

{% for item in remainder %}

{{ item.title }}

{% endfor %}


Need to access year/month variable when grouping entries by date

If I understand your example correctly, a simple hyphen would do the trick — "YYYY-MM" is a format the date filter recognizes.

{% set entries = ... %}
{% set entriesByMonth = entries|group('postDate|date("Y-m")') %}
{% for month, entries in entriesByMonth %}

        {{ entries | length }} entries in {{ month|date("F Y") }}

{% endfor %}


How to add active class to homepage nav list item

Unless the URL is domainname.com/homepage then your class will not get added.

Are you using template layouts? If you are you could have something like this in your _layout

{% block bodyClass %}{% if bodyClass is defined %}
{% else %}
{% endif %}

Then in your home template you would set it like so:

{% set bodyClass = 'CLASSNAME' %}

OR you could something like this in your nav:

Home

Work

About

#

Hopefully that helps. If not you can always look at this post with other methods:

How can I add a dynamic "active" CSS class to the navigation on any given page?


Outputting SVG from an asset field inside a matrix field with svg()

Ok, think I know what's wrong – you want to select the first asset, but not its url. E.g.
{{ svg(callout.icon.one()) }}


Can I set the same relation in a field multiple times?

You're right, this can only be accomplished with a Matrix field.

That said, you could probably accomplish what you need via a custom field type. You'd need to create a custom plugin (obviously), but you could probably build something that simply stores an array of asset IDs:

[12,33,42,10,10,10]

I won't diver deeper into what the mechanics of that plugin & field type should be... that's a bit beyond the scope of this question.


Build array from nodes from RSS where keys contain colons

As @mats-mikkel-rummelhoff suggested, that data type is an array. So I was able to get the desired value by using:

'img' : node['media:content'][1]['@url']

Thanks, Mats.


Redactor plugin for Bootstrap Responsive Image

For those who find this, After some more digging into Redactor, looks like Craft overrides the original button to accommodate for sources and transforms in RichTextInput.js at  onImageButtonClick - line 261.

onImageButtonClick: function()
{
    this.redactor.selection.save();

    if (typeof this.assetSelectionModal == 'undefined')
    {
        this.assetSelectionModal = Craft.createElementSelectorModal('Asset', {
            storageKey: 'RichTextFieldType.ChooseImage',
            multiSelect: true,
            sources: this.assetSources,
            criteria: { locale: this.elementLocale, kind: 'image' },
            onSelect: $.proxy(function(assets, transform)
            {
                if (assets.length)
                {
                    this.redactor.selection.restore();
                    for (var i = 0; i < assets.length; i++)
                    {
                        var asset = assets[i],
                            url   = asset.url+'#asset:'+asset.id;

                        if (transform)
                        {
                            url += ':'+transform;
                        }

                        this.redactor.insert.node($('<img src="'+url+'" />')[0]);
                        this.redactor.code.sync();
                    }
                    this.redactor.observe.images();
                }
            }, this),
            closeOtherModals: false,
            transforms: this.transforms
        });
    }
    else
    {
        this.assetSelectionModal.show();
    }
}

Ended up using Retcon Twig filters plugin to add the class:

{{ entry.body|retconAttr('img', {class: 'img-responsive'}) }}