Is it possible to limit the locales for asset meta fields?

Can I just delete the unwanted entries in the content table?

No, definitely don’t do that.

If you only want to enter captions in a couple languages, fine. Just ignore the other locales.

Then from your templates you can always have Craft fetch the assets with the DE or EN content, by setting the locale param.

{% set assetLocale = (craft.locale == 'en' ? 'en' : 'de') %}

{% for asset in entry.myAssetsField.locale(assetLocale) %}
    {{ asset.caption }}
{% endfor %}


Receiving duplicate Sprout Form submissions

I believe the issue here is most likely that you just need to add the modifyForm hook to your custom templates. All the Captchas look for that hook and output the necessary hidden input fields and javascript that they need to do their thing when the form loads.

You can see how we include the modifyForm hook in the default templates. It can be added anywhere within the  tags.


FeedMe - Extracting attribute from an RSS feed field

I'm unable to view the feed via the link you've provided - seems like it may not allow public access. In any case, see a working example below using an example public RSS feed.

{% set params = {
    url: 'http://www.feedforall.com/sample.xml',
    type: 'xml',
    element: 'item',
} %}

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

{% for node in feed %}
  {{ node.category.attributes.domain }}
{% endfor %}


Element API plugin - Return message when no results are found

Currently, Element API is hard coded to throw a 404 exception for single element endpoints, if the element criteria returns no results. There's no way to prevent this exception, add "fallback" criteria or to display an error message.

Note that the 404 exception will only be thrown if the first parameter is set to true, though. If it isn't, Element API will just return an empty dataset.

Obviously, omitting the first parameter is not a real solution to your issue. You still have no way to set a custom error message, and it would also mean that all single element endpoints would return arrays, as well as paging metadata etc, instead of a "flat" JSON object.

On that note, my opinion is that the canonical answer to this question should probably be to fork the Element API plugin and/or add a feature request.

However, if you don't want to go down that road, here's a possible workaround. It's not pretty :)

Basically, what you'll need to do is to catch the HttpException, in order to return a custom payload.

To do this, you'll need to write a custom plugin. Important: make sure that the string returned by your plugin's getName() method comes before "Element API", alphabetically. The reason for this is that you need to make sure that Craft loads your plugin before the Element API plugin (Craft loads plugins alphabetically, by name). I'll pretend you opt for the name "Awesome Plugin", which would work nicely.

Your plugin will need a controller, so create one called "AwesomeController" or the like. This controller should have a method called actionGetElements, taking the same arguments as the ElementApiController's actionGetElements method.

The only purpose of your controller is to "wrap" the ElementApiController, in order to catch the 404 HttpException fired by Element API, and echo a custom error message. Here's how that could look:

<?php
namespace Craft;

class AwesomeController extends BaseController
{

    protected $allowAnonymous = true;

    public function actionGetElements($configFactory = null, array $config = null)
    {
        try {

            // Fire up the Element API controller
            craft()->runController('elementApi/getElements');

        } catch (HttpException $e) {

            switch ($e->statusCode) {

                case 404 :

                    // It's a 404. Output a custom error message
                    JsonHelper::sendJsonHeaders();
                    echo JsonHelper::encode(array(
                        'error' => 'No element found',
                    ));
                    // End the request
                    craft()->end();

            }
        }
    }

}

Obviously, the controller will do nothing by itself – the final thing you need to do is to "hijack" the Element API routes; making them point to your controller instead of the ElementApiController. To achieve this, you'll need to create a method called registerSiteRoutes() in your plugin's primary class. Inside this method, you'll basically want to pull all the routes from the Element API plugin, changing their action value to awesomePlugin/getElements.

This is why it's important to make sure that your plugin is loaded by Craft before the Element API plugin: when an existing route is added to Craft, it'll be ignored. This means that for every endpoint in /config/elementapi.php, you can trick Craft into loading your custom controller instead of ElementApiController!:

Here's how that registerSiteRoutes() method could look:

public function registerSiteRoutes()
{

    $routes = [];

    // Get the Element API plugin
    $elementApiPlugin = craft()->plugins->getPlugin('elementApi');

    if (!$elementApiPlugin) {
        return $routes;
    }

    // Get the Element API routes
    $elementApiRoutes = $elementApiPlugin->registerSiteRoutes();

    // Set action property
    foreach ($elementApiRoutes as $endpoint => $config) {
        $config['action'] = 'awesomePlugin/getElements';
        $routes[$endpoint] = $config;
    }

    return $routes;

}

All in all – not exactly an elegant solution; but if the 404's are a dealbreaker to you, its at least a working workaround that doesn't require you to tamper with the Element API source, and the performance footprint should be minimal, too (no redundant database queries).


I think it'll be easier and more efficient to achieve that if you use the loop functionality instead of querying the actual tags. I think this code does what you want:

{% set topics = '' %}

{% for topic in entry.topics %}
    {% set topics = topics ~ topic ~ (loop.index < loop.length-1 ? ', ' : loop.index < loop.length ? ' and ') %}
{% endfor %}

This is a sentence with {{ topics }}.


Loading javascript on specific sections/pages

A safe way to add JavaScript resources via the frontend, is to use the {% includeJsFile %} Twig function in your template. The nice thing about the includeJsFile function is that it doesn't matter where in your template you call it; the file(s) added will always be output just above your </body> tag (or wherever else you put your {% getFootHtml() %} call). Also, the function makes sure that no duplicate resources are requested, even if you have multiple calls to includeJsFile using the same URL (or filepath, for local resources).

You're not being specific about why the JavaScript should only be loaded for a specific entry, so it's difficult to advise about the optimal way to achieve this – but there's a few different approaches that could work nicely:

For one, you could add a conditional to your template, where you hard code the ID to the entry in question:

{% if entry.id == 100 %}
    {% includeJsFile('https://code.jquery.com/jquery-3.0.0.js') %}
{% endif %}

Of course, you can have the conditional look at other attributes, as well:

{% if entry.section.handle == 'awesomeSection' %}
    {% includeJsFile('https://code.jquery.com/jquery-3.0.0.js') %}
{% endif %}

If the JavaScript should e.g. be loaded whenever a certain Matrix block type is output, you could do something like this:

{% for block in entry.matrixField %}
    {% switch block.type %}
        {% case 'someBlockType' %}
            ...
            {% includeJsFile('https://code.jquery.com/jquery-3.0.0.js') %}
    {% endswitch %}
{% endfor %}

Remember, includeJsFile handles duplicate requests for you, so it doesn't matter if there's more than one someBlockType block – the actual external JS resource will only be requested once.

Of course, the most flexible option – and the one I would recommend – would be to add a custom field to your entry type, where you can add URL(s) to external scripts that should be loaded. This makes it easy to add external JavaScript resources to any entry, via the regular editing form in the CP. For this, the Table fieldtype will do nicely (the following assumes a table field with the handle externalScripts and a single column called url):

{% for row in entry.externalScripts %}
    {% if row.url %}
        {% includeJsFile(row.url) %}
    {% endif %}
{% endfor %}

Finally, another approach would be to add a PlainText field to your entry type (multiple lines, i.e. a textarea), where you can paste in a full <script> tag, e.g.:

    <script src="https://code.jquery.com/jquery-3.0.0.js"   integrity="sha256-jrPLZ+8vDxt2FnE1zvZXCkCcebI/C8Dt5xyaQBjxQIo="   crossorigin="anonymous"></script>

If go down this path, you can't use includeJsFile and will have to output the string "manually" – making sure to add the |raw filter to prevent Twig from escaping the HTML (the following assumes your plaintext field is called scripts):

{{ entry.scripts|raw }}

For the latter option, you might want to add a {% block scriptsInFooter %} to your base layout, in order to have the value for the scripts field render in the appropriate place:

{# Entry template #}
{% block scriptsInFooter %}
    {{ entry.scripts|raw }}
{% endblock %}

{# Base template #}
    ...
    {% block scriptsInFooter %}{% endblock %}
</body>


How to duplicate a page within a Structure?

There are two easy ways to avoid copying and pasting or having duplicate entries.

First, you can use Globals to store the shared information.

Alternatively, your second entry/template can just ask for the data from the entry of the first entry.

{% set shared_information = craft.entries.slug('my-first-entry-slug').first() %}

<p>{{shared_information.customFieldWithSharedInformation}}</p>


AJAX Front-end User Registration Form not displaying macro errorList

No errors are displayed because you are using AJAX to post your data. The errorList function works only with "regular" POST flow. When ajax response is available you need to grab it and append errors yourself.

Try this code:

$('#registrationForm').submit(function(ev) {
    ev.preventDefault();

    var data = $(this).serialize();

    $.post('/', data, function(response) {

        if (response.success) {
            console.log("success")
        } else {
            console.log(response.errors);
            appendErrors(response.errors);
        }

    });
});

function appendErrors(errors) {
    $.each(errors, function(field, errors) {
        appendError(field, errors);
    });
}

function appendError(field, errors) {
    var $errorList = $('<ul>');

    $.each(errors, function(index, error) {
        $errorList.append($('<li>').html(error));
    });

    $("input[name=" + field + "]").after($errorList);
}


How to create entry from external app webhook?

You would need to set this up using a plugin. The plugin would, at a minimum, contain a controller, with an 'action' method designed to handle the url request and generate an entry; using 'post' or 'get' to pass parameters to the controller action.

public function actionAddEntry()
{
    // retrieve parameters
    $title             = craft()->request->getParam('title');
    $customField1      = craft()->request->getParam('customField1');
    $customField2      = craft()->request->getParam('customField2');

    // create a new entry model and set content attributes
    $entry = new entryModel();
    $entry->sectionId  = 2;
    $entry->typeId     = 2;
    $entry->authorId   = 1;
    $entry->enabled    = true;

    $entry->getContent()->setAttributes(array(
        'title'        => $title,
        'customField1' => $customField1,
        'customField2' => $customField2,
    ));

    // save entry
    $success = craft()->entries->saveEntry($entry);

    // handle success or failure
    if ($success) {
        // log result or send yourself an email or whatever
    } else {
        // log error
    }
};

By default however, controller actions are only accessible to logged-in users. If you want to allow anonymous access you would need to specifically allow it using the $allowAnonymous property. This definitely introduces some security issues, so proceed with caution. Ideally you would want to set up some kind of authentication, or only accept requests from known hosts.


How to relate a long survey to a user and later query by values

When you're dealing with that many fields it's definitely a non-trivial undertaking but Craft does have all the tools you need to pull it off.

Your plan B is probably the most solid option. Make a new section that houses the skill entries and then set up all the radio buttons on it you'll need.

You can put fields on Users directly but it gets weird as they don't act like entries in some respects.

Getting all the fields into Craft is probably another topic that you'll probably want to do programatically.  However,  after you have them all in the CMS, it's relatively straightforward to spit out all the fields for a particular entry type in a section.

To do that:

{# get the section by handle #}
{% set section = craft.sections.getSectionByHandle('skillRecords') %}

{# fields are set on entry types of sections to get all the entry types #}
{% set entryType = section.getEntryTypes %}

{# loop through the fields in the first entryType's fieldLayout Model #}
{# if you have more than one entry type, use 1, 2..etc #}

{% for fieldLayoutField in entryType[0].getFieldLayout().getFields() %}

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

    {# grab the type of field from its className #}
    {% set fieldType = field.className|replace({'craft\\fields\\':''}) %}

    {# output the field #}

    {% switch fieldType %}

     {% case 'RadioButtons' %}
     <fieldset>
     <legend>{{ field.name }}</legend>

    {% for option in field.options %}

        {% set selected = entry is defined ?
                          field.value == option.value : option.default %}

        <label>
            <input type="radio"
                name="fields[field.handle]" value="{{ option.value }}"
                {% if selected %}checked{% endif %}>
            {{ option.label }}
        </label><br>

       {# you'll probably  want to make other cases depending on what you're doing #}
    {% endfor %}
    </fieldset>

  {%endswitch%}

{% endfor %}

That's a pretty simple example with zero styling so you'll obviously want to make it your own. As with anything in Craft, the front end and the UI is up to you.

You might consider splitting up the questions into pages (eg 30 per page) and save the form after every page (either in the user's browser or to Craft itself). Vue or even jQuery can help you do that.

I'm not sure what the performance aspect is going to be when it comes to 120 fields. The most performant way would be to setup your own table with its own values but that goes down the rabbit hole of plugin development.


Plugin access and control panel navigation

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

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


Search entries AND within associated assets fields

I have now found a workaround using the information @brad-bell provided, that is working, but not exactly what I wanted:

{# Normal search #}
{% set resultsA = craft.entries(search_criteria).ids() %}

{# Assets search #}
{% set assets = craft.assets.customFieldName('*'~query~'*') %}
{% set resultsB = craft.entries.relatedTo({
        targetElement: assets,
        field: 'customFieldName'
    }).ids() | without(resultsA) %}

{# Merge results, paginate #}
{% set results = resultsA | merge(resultsB) %}
{% paginate results.limit(10) as pageInfo, pageEntries %}

How I did it:

Perform a normal search for entries containing the query in one of their fields (specified in search_criteria, not included in the code above) and get the IDs of the found entries.
Search for assets that contain the query in their customField. Since I'm only searching one field, I do not use the search-function, which would be an option when searching multiple fields.
Now I'm getting the entries that are related to the assets. As in step 1, I attain the IDs, ignoring IDs already present in the first set of results, to avoid duplicates (which I found out late are not a problem, since craft.entries - in point 5 - only returns each entry once)
I merge both arrays.
Get an ElementCriteriaObject containing all entries with the IDs collected before.
I paginate them as usual.

If you do not need to paginate, step 5-6 are might be unnecessary. You could simple use find() instead of ids() to get arrays which you then could merge. This however will cause duplicates!

Although this code works, it has a few disadvantages:

The results are ordered by their position in both arrays. resultsA are listed first, followed by resultsB. In my application I can live with that, since queries fetching many results in assets will usually fetch almost no results in entries and vice versa. I tried to sort and order them by the number of occurrences, however, this did not work using only twig functions. With the help of a simple plugin as host for some php array sorting, ordering of the results could be improved.
Performance is not very good, since many queries are necessary.

Idea

One idea in my mind was to build a custom MySQL-query, which JOINS the assets fields (combined to a string if there are multiple ones) to the entry's row. However, I was not able to accomplish that. If anyone knows how to do so: Let me know!

Thanks for your help!


Programatically add lines to a Super Table field

Got it!

In case you just want to add lines (or Blocks) to a SuperTable field of an entry, no need to update the entry itself, you "just" have to create new Blocks with correct type, field and entry.

    $field = craft()->fields->getFieldByHandle('mySuperTableField');
    $blockTypes = craft()->superTable->getBlockTypesByFieldId($field->id);
    $blockType = $blockTypes[0]; //Only 1 Type of Blocks in the SuperTable
    $typeId = $blockType['id'];

    $block = new SuperTable_BlockModel();
    $block->fieldId = $field->id;
    $block->typeId = $typeId;
    $block->ownerId = $entryId; //this is the entry id

    $block->setContentFromPost(array(
        'categoryOne' => [$catOne->id],
        'categoryTwo' => [$catTwo->id],
        'textField' => 'blablable...'
    ));

    $success = craft()->superTable->saveBlock($block);


How to set CC or BCC emails to EmailModel?

The way you do it now only adds email addresses as an array. You'll have to specify both email and name keys too, so it becomes like this:

$email->cc = array(
    array('email' => 'email@email.com', 'name' => 'Name')
);


Adding a County input field into Address in Craft Commerce

Currently (Dec '16) - custom fields are not able to be used with addresses in Commerce.

Your best best is probably to add a field to your orders and pretend it's on addresses, but obviously if you deal with multiple addresses, as you probably do, that gets a bit tricky quickly.  You could implement a plugin that has it's own table of records that associate addressIDs with a county field.

I am pretty sure it's on the Commerce radar but you're a bit stuck right now I think, without some extra work.


How can I ensure using actionUrl in my template does not show script name in the generated URL?

actionUrl() and UrlHelper::getActionUrl() always force the script name to show up despite the omitScriptNameInUrls config setting for two reasons:

Action URLs are generally not actually visible to end users, so there’s no point in hiding “index.php” from them (computers don’t care about aesthetics).
They are often used for POST requests, and your index.php redirect in .htaccess will drop any POST data associated with the request.

That said, if you really want to create an action URL that omits “index.php”, you can do this:

{{ url(craft.config.actionTrigger ~ '/your/action/path') }}

(I don’t think your use case is valid though. Just commented on it.)


Cannot create entry when Entry Type has Title field hidden

I was using the Twig template syntax ({{varName}}) in the Title Format field on the Entry Type instead of the proper syntax ({varName}).


How to disable element editor on custom element type?

The Element Editor HUD will only be available if your element model’s isEditable() method returns true. (It returns false by default.) Remove that method from your element model class and you should be good.


Getting "Internal Server Error: Function 'dump' does not exist" when accessing/creating custom fields

Adding as an answer because it was confirmed via a support ticket that a plugin was at fault.

Twig's dump method is only available in Craft when devMode is enabled.

Turn it off, reproduce the problem, then search your craft/storage/runtime/logs files for [error].

The stack trace listed in that error log will show which plugin is causing the issue.

Chances are that plugin is calling Twig's dump somewhere in a template, assuming it will always be available, when that is not the case.


I assume you're referring to the archived column in the craft_users table in the database.

Originally we were going to use that as a way to "soft delete" different elements in Craft (Users, Entries, etc.), but never got around to implementing it for various reasons, so there is no UI for it and no backing code to support it currently.


Entries Field Type showing all entries instead of entries selected

You need to use the relatedTo parameter

{% for entry in craft.entries.relatedTo(block).section('sessionTiles').all() %}

or even more simple the short syntax

{% for sessionTile in block.blockTilesContent.all() %}


Set duration of 'newpassword' link validity via config/general?

The setting you're looking for is verificationCodeDuration which defaults to 24 hours (86400 seconds).
https://docs.craftcms.com/api/v3/craft-config-generalconfig.html#verificationcodeduration
(And see craft\helpers\ConfigHelper::durationInSeconds() for a list of supported value types)


Is it possible to grab related entries that have been attached to a certain field?

If you want to limit your relationships to a particular field, use this syntax:

$criteria->relatedTo = array(
    'targetElement' => $element,
    'field' => $field
);

I believe 'field' will take:

1) A single or array of $field instances

2) A single or array of field IDs or field handles.


You can try clearing your cache, and/or emptying the contents of the /craft/storage/runtime/ folder. If it's just some cached data causing a problem, that would fix it.

Otherwise, I'd recommend waiting for P&T to get back to you... they're really the only ones who can verify and correct your licensing issues.


Best practice for channels and structures

You basically have two options for creating a "listing" or "archive" view for your Channel or Structure sections.

The first option is to create a Single. This is in many cases appropriate, e.g. if you need to add content to the listing view in addition to the actual entry list, such as a visual banner, introductory text etc.

Inside the Single section's entry template, you'll need to pull the entries you want to display in the list using craft.entries – here's a very basic example for how the Single section's entry template could look:

{% extends '_layout' %}

{% block content %}

    {# Display some content from our Single #}

{{ entry.title }}

{{ entry.introduction }}

    {# ...and a list of entries in the "news" Section #}

Entries

        {% for newsEntry in craft.entries.section('news') %}

{{ newsEntry.title }}

        {% endfor %}

{% endblock %}

The second option is to not create a Single :) Of course, then you need to solve the problem of there not being an actual URL for your "archive" or "list" view.

There are many ways to approach this, but a simple and good solution to this problem is to leverage Craft's template routing pattern. If your Channel or Structure section's URL format is news/{slug}, and the entry template is news/_entry.html, you can simply create a template called news/index.html, and Craft will render that template for any requests to example.com/news.

Without a Single, the templates/news/index.html template will look much the same as the above example (you'll still need the craft.entries query to actually pull the entries) albeit without a pre-populated entry variable:

{% extends '_layout' %}

{% block content %}

News archive

Here's our awesome news archive

Entries

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

{{ entry.title }}

        {% endfor %}

{% endblock %}

About "Craft's template routing pattern" mentioned above; these are two important things to know about:

– Whenever Craft can't match a URL request to an entry or category (and also no dynamic routes) it'll look for a matching template path. This means that if there's no entry or category with a URL format matching the request example.com/news, Craft will look for a template with the filepath /templates/news/index.html. If that template exists, Craft will render it.

– Any template prefixed with an underscore (or in a folder prefixed with an underscore), such as /templates/news/_entry, is excluded from template routing. This means that Craft won't match the URL example.com/news/entry to the news/_entry.html template.


How do I relate a user to a channel entry from a form?

When saving an entry field type as part of your plug-in it needs to be an array of IDs in order to work correctly. This can either be handled via a plug-in or in the form by passing the value as an array to that field handle.

Plug-in:

$user->setContentFromPost(array(
    'entryField' => array(10)
));
$success = craft()->users->saveUser($user);

Front-end form:

<input type="hidden" name="fields[relatedEntry][]" value="{{entry.id}}">


How to display all entries within a given category

Your mistake is in getting the category. Instead of what you have try:

{% set category = craft.categories.group('allcategories').slug('photos').find() %}

Getting elements in Craft use ElementCriteriaModel and find(), first(), last(), &c. do not accept any parameters (though nth() is an exception to this). So you need to search by other fields in the element as per the docs.

You may also want to make sure that the slug of the category group is not camel case (allCategories as opposed to allcategories).


Event or hook when user account email validated

There currently aren't any verification events, but if the user is in a pending state (i.e. they haven't been activated yet), verification will trigger activation, which triggers the onBeforeActivateUser and onActivateUser events.


Inline image transform using Matrix field for image quality?

Aha!!! Got it working at last!!

As I was using Live Preview, even though I was set to Dev Mode for any errors, they weren't showing in the Live Preview pane (maybe that should be a feature request?).

As soon as I tested it out on the live page I saw an error and it told me to place parentheses around an expression so I did this instead :

quality: (block.quality.value) and all is good with the world now!! :-)


Twig template outputting blank page on non-"dev" environment

It looks like you're reinventing the wheel here: in Settings → General, you can toggle the site live/offline. When the site is offline, Craft serve the templates/503.twig templates, no matter which URL you hit.
You can even configure users to have access to the site, when it's offline. To do so, go to the user edit page in the control panel and then to the Preferences tab.

Regarding your specific blank page issue, it's caused by a mixup between the Twig include function & the Twig include tag.
Function
As per the documentation:

The include function returns the rendered content of a template.

You then have to do something with the returned value or it is pointless.
Tag
The documentation of this tag is misleading. It states that :

The include statement includes a template and returns the rendered content of that file

but what it really does is output the rendered content of that file.
In your case, you use the function but forget to output its value. To fix you're issue, you can either use output delimiters ({{ include('/maintenance') }}) or use the tag instead of the function ({% include'/maintenance' %}).
The documentation of the include tag encourages us to prefer the former:
As of Twig 1.12, it is recommended to use the include function instead as it provides the same features with a bit more flexibility
Solution
TL;DR
Use {{ include('/maintenance') }}.


User Registration - Keep as inactive until verified by admin

Some sort of workaround

You can make a register user group with no permissions.
Than add another group with the permissions you want.

After registration, the admin can put a new user to the new group.


Craft 3: Environment variables are not parsed when used in Assets source field

Environmental variables as such don't exist "as a thing" in Craft 3. Instead, you'd define your Volumes in the AdminCP and override anything you need in craft/config/volumes.php

You can see an example of how to do it here: Craft 3 Multi-Environment


Using MySQL With just InnoDB storage engine

Actually, all the tables, but one use InnoDB storage engine. The one that uses myisam engine is table "searchindex".
When you check for index type:
mysql> show index from searchindex where Index_type="FULLTEXT" \G

you get that the "searchindex" table indeed uses FULLTEXT.
I would say that Craft uses some specific fulltext searches specific to myisam engine, therefore not using innodb.
You can change the engine of the "searchindex" table (and see what brakes) with:
mysql> alter table searchindex engine="InnoDB";

and revert with:
alter table searchindex engine="MyISAM";


Craft 3 Element API Authentication/Login

First of all passing the password and username as query strings is one of the most insecure things you can do. It would highly suggest you to not do that unless you want to expose your accounts to everyone with minor knowledge.

Furthermore you are mixing Craft 2 with Craft 3. There is no userSession in Craft 3. I don't want to post a code snipped that would work with the way you are trying since would could eventually copy it without knowing the harm it might cause.

In the end: you should either create some kind of access token, don't pass the params via get request or do something similar. Globally passing sensitive data via url is not clever


So this would be a better solution:

{{ entry.title|replace('/^Nobel /', '') }}

Thanks for the support Craft!


Merge two queries of entries ordered by publication date

You can probably use the relatedTo parameter with multiple relation criteria:

{% set entries = craft.entries.section(['news', 'press']).relatedTo('or',
    { targetElement: newsTypeCategory, field: 'newsTypeCategoryField' },
    { targetElement: pressTypeCategory, field: 'pressTypeCategoryField' }).order('postDate desc') %}

Note that newsTypeCategory and pressTypeCategory should be category IDs (or CategoryModels) so you might need to pull the relevant categories as well:

{% set newsTypeCategory = craft.categories.group('newstype').slug('someslug') %}
...

Also note that you'll obviously need to change the field values to the real handles for your Categories fields, in the example criteria above.

An alternative approach is to use the SuperSort plugin to sort two arrays of entries on the postDate attribute:

{% set newsEntries = craft.entries.section('news').relatedTo(newsTypeCategory) %}
{% set pressEntries = craft.entries.section('press').relatedTo(pressTypeCategory) %}
{% set allEntries = newsEntries|merge(pressEntries)|supersort('sortAs', '{ postDate }') %}


Build a language switcher for a one page website?

The basics for setting up your localized site are nicely written down in the Localization Guide. This walks you through the steps necessary to make your site being available under their subfolders /de and /fr.

Set up correctly, your templates will always show the field content translated to the currently accessed locale.

If your one-pager template is not connected to an entry (case 4 in the Routing article) and you simply save your template files at templates/de/index.html and templates/fr/index.html (case 6), have a look at the include tag, that allows you to maintain one template responsible for all of your locales (e.g. {% include '../de/index.html' %}).

The following code is a simplified version of the example I wrote down here, and should do fine for a one-page website:

{# Loop through selected site locales #}
{% set locales = ['de', 'fr'] %}
{% for locale in locales %}

    {# Check if `locale` equals the requested page locale #}
    {% if locale == craft.locale %}
        {% set current = true %}
    {% endif %}

    {# Output a link to the hompage and add a class "current" to the current locale's link #}
    {{ craft.i18n.getLocaleById(locale).name }}

{% endfor %}


Craft Commerce WorldPay integration callback failure

I have answered your support ticket and given you the fix for worldpay. It will be included in the next release of Craft Commerce.


Filtering category objects in a template?

You can do

{% set ids = myGlobal.liveCategories.ids() %}
{% set category = craft.categories.slug(craft.request.getSegment(3)).id(ids).first() %}
{% if category %}
    The category is valid
{% else %}
    No slug found, or the category is not in the list
{% endif %}

Explanation: you grab all the ids from your allowed categories and search for them in your query. If a category is found it is one of the allowed categories. If not the category is another one or the there is no element with a matching slug.


What's the difference between ElementCriteriaModel and DbCommand?

DbCommand represents a SQL statement to execute against a database.

ElementCriteriaModel is a model just like any other model in craft/app/models, but it also happens to make it easy to search for Elements in the database.

By setting all of the criteria for the elements you're searching for and calling the find() method, that will invoke craft()->elements->findElements($this);, which in turn will create a DbCommand object custom built for the ElementCriterialModel parameters that you set.

So think of ElementCriteriaModel as an abstraction on top of DbCommand that makes it easy to search for Elements.


Using the Guest Entries plugin, how can I allow people to edit/delete?

What you could try is to use the Preparse plugin and add a field to your entry type that automatically generates a secret key for each submitted entry.

Show the user this key on the page they are redirected to upon form submission, tell them to write it down.

You now set up a new guest entry form to submit matches. So instead of deleting entries, the user enters his personal secret key into a field to submit a new entry (I'd suggest to post to the same channel but different entry type).

On the front-end you can now list only those requests/offers entries that do not have a matching "delete" entry yet. Another advantage over your delete approach is that you have a nice record and overview in the CP of what was offered and when.

Code example:

There's no template function to generate a random string, but you could apply Craft's shuffle function on an array of characters.

{%- set chars = '012345678901234567890123456789'|split('') %}
{%- set key = shuffle(chars)|join %}

{{- key|slice(0, 6) }}

That's how you could generate the secret keys within the Preparse field. And to loop through your "requests" and only show them if there's no matching "response" entry yet, do something like this.

{% set requests = craft.entries({
    section: 'lifts',
    type: 'requests',
    limit: null,
}) %}

{#
 # Loop through all "requests". Check for each of them if there's a
 # matching "response" before outputting.
 #}
{% for request in requests %}

    {#
     # Try to get an entry of entry type "responses" where the "secretKey"
     # field value matches the "secretKey" of the "request" in the current
     # itteration of this "requests" loop (returns an EntryModel or NULL).
     #}
    {% set hasResponse = craft.entries({
        section: 'lifts',
        type: 'responses',
        secretKey: request.secretKey,
    }).first() %}

    {#
     # Only output if "hasResponse" is not NULL
     #}
    {% if not hasResponse %}
        {{ request.message }}
    {% endif %}
{% endfor %}


How to make plugin developer name available in templates?

Data in plugins is not automatically made available to twig templates.

To make something available, you need to create a folder in your plugin master folder called variables and in that folder create a class PluginNameVariable.php

Here's an example of what you might put in that file:

<?php

namespace Craft;

class YourPluginNameVariable
{

    public function developerName()
    {
        return craft()->yourPluginsName->someServiceMethodThatReturnsTheDeveloperName();
    }

}

This would make a template variable available in your templates via

{{ craft.yourPluginName.developerName }}

Here are the Craft Docs for this - https://craftcms.com/docs/plugins/variables


CP entries structure tree view folded (not expanded) by default?

The structure of the tree is stored into local storage on the user's browser, so as long as that is not cleared, then the position of each of the nodes should be remembered between requests.


Create a specific order of paginated entries by entry type

If I get you right, you want to exclude the premium entries from the others? Carefull, code is not tested ;)

{% set premiumEntries = craft.entries({
    section: 'offers',
    entry-type: 'premium',
    order: 'postDate desc'
}) %}

{% set standardEntries = craft.entries({
    section: 'offers',
    entry-type: 'standard',
    order: 'postDate desc'
}) %}

Then you need to do a loop to merge the standard to the premium.
Something like this
Merge two arrays of ElementModels?

... and finally paginate trough all of them.
Hope that helps.


entries.onSaveEntry does not fire from frontend

Where is your "craft()-on()" code located?

Per the documentation, the best place is in your primary plugin file in a method named "init()".

https://craftcms.com/docs/plugins/hooks-and-events#listening-for-events

For example, here's mine:

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

    // event triggers
    craft()->on('charge.onValidate', array($this, '_validateRegistrationForm'));
    craft()->on('entries.saveEntry', array($this, '_processEditPricelistLocationForm'));
    craft()->on('entries.saveEntry', array($this, '_processEditGuestUsersForm'));
    craft()->on('entries.saveEntry', array($this, '_processGuestUserAccessForm'));
    craft()->on('entries.onBeforeSaveEntry', array($this, '_processEditGuestRemoveUsersForm'));
}

and here's just showing that I do in fact handle the Event $event in the method:

/**
 * Charge onValidate
 *
 * @param Event $event
 */
public function _validateRegistrationForm(Event $event)
{
    // do stuff
}


How might I select specific data in an entry to be displayed when selecting an entry?

Probably a dozen different ways to tackle this, but I'd probably use Craft's flexible relationship engine by creating a Bios channel and a Jobs channel.

The Bios channel would have an entries field assigned to its field layout with its source set to Jobs and it would allow for multiple selections.

Then, when creating a new Bios entry, you'd select the Job(s) for that person.

You could pull them out into the front-end however you'd like at that point.


Getting error in template: Impossible to access an attribute ("getUrl") on a NULL variable ("")

You can just test if image is defined first using:

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


Plugins - Element Criteria Model. Can I return only entries with a updated date in the last 7 days?

I'm not sure if there's some other Craft helpers / static variables that you could use, but this technique works. Create a DateTime object without the param set to get the current time, modify it and format it for use in the query like so:

$date = new DateTime();
$date->modify('-7 days');

// Format datetime for use in query
$timezone = new \DateTimeZone(DateTime::UTC);
$date = $date->format(DateTime::MYSQL_DATETIME, $timezone);

$criteria->dateUpdated = '> '.$date;


How do I pull an image from a child entry of a structure

property.imageBackground is an ElementCriteriaModel, which is to say that it always behaves much like an array of assets (even if you are sure there is only one).

So the short answer is that you need:

style="background-image: url({{ property.imageBackground.first.url }});"

The catch here is that this will fail if there is for some reason no such asset. This can happen even if the field is required, and so you should always check. There are several ways to check. This is straightforward:

{% if property.imageBackground|length %}
  {{ property.imageBackground.first.url }}
{% endif %}

Or you can use a loop:

{% for background in property.imageBackground %}
  {{ background.url }}
{% endfor %}

Or a default (this uses twig's ?: operator, and relies on some global image always being there, but you now only have one image to make certain is always there):

{% set background = property.imageBackground.first
   ?: g_config.defaultBackgroundImage.first
%}
{{ background.url }}


Why can't I drag and drop fields in settings on a mobile phone?

Touch screen devices don't "drag & drop" in a traditional sense, because dragging your finger around the screen is generally reserved for scrolling. This issue isn't specific to your browser or device, it's the same behavior across all touch screen devices.

Depending on how you want to look at this, I'd consider this either a "bug" or a "feature request". Assuming we're going with "feature request", your best course of action is to formally submit your request here:

  http://feedback.buildwithcraft.com/


When onAfterElementSave is called check for save as draft or publishing?

Actually, onAfterElementSave doesn't get called at all when saving a draft, so there's nothing to worry about.

When you load a draft in the CP, your field type will be passed in a $value based on the POST data for the field back when the draft was last saved (which is the same thing that happens when saving an entry fails due to validation errors).


Problem pulling Tweets with media using Dukt's Twitter API plugin

The return from craft.twitter.get() is not an array of tweets, but a response object, where the actual tweets are nested in an attribute called data.

Not tested, but from looking at the plugin docs, something like this should do it:

{% set response = craft.twitter.get('statuses/user_timeline', { tweet_mode:'extended' }) %}

{% if response.success %}
    {% for tweet in response.data %}
        ...
    {% endfor %}
{% endif %}


Try to group the entries sorted by size using the group filter:

{% set entriesSorted = entries|supersort('sortAs', '{ size }', SORT_NUMERIC) %}
{% set entriesByBrand = entriesSorted|group('brand.first.title') %}
{% set entriesByBrand = entriesByBrand|supersort('ksort') %}

{% for brand, entriesInBrand in entriesByBrand %}
    {% for entry in entriesInBrand %}
        <li>{{ entry.title }}</li>
    {% endfor %}
{% endfor %}


onBeforeSaveUser event does not fire if basic user fields do not validate

I agree it's unexpected behavior, but for Craft 2 it won't change.

Craft 3 had a major overhaul of its event system and validation workflow where it works as you'd expect, though.


craft.users.admin boolean parameter... to quote or not to quote?

Let me try to make some sense of the behavior you’re seeing.

First, you should know that the admin param will query against the admin column in your craft_users table, which will either be set to 0 or 1 for each user.

Like most Craft params, the admin param is set to null by default, and will only have any affect on the DB query if it is set to a non-empty value. (Here’s a list of what PHP considers “empty”: http://php.net/manual/en/function.empty.php#refsect1-function.empty-returnvalues)

So, here’s what’s happening behind the scenes for each thing you passed in:

false – That’s an empty value, so it’s the same as not passing anything in.
'false' – Since the admin column is numeric, MySQL has to normalize this string into a number (sortof like using JavaScript’s parseInt() function). The result for 'false' is 0, since 'false' doesn’t begin with a number. The end result is that this awkwardly works as expected, but I wouldn’t recommend it.
'true' – Same effect as 'false'. Ends up being 0.
true – SQL doesn’t support PHP’s boolean datatypes (true/false), so PHP will convert this to 1 before passing it off to MySQL. (false likewise becomes 0, but since false is empty, Craft won’t let your value make it that far in the first place.)

In the future, I think this makes a good case for us allowing false, so we’ll probably start checking for that and allowing it. But that won’t help you today.

So the question is then, what is the best way to find users that are(n’t) admins today? Here’s what I would recommend:

Finding admins:

1 (int)
'1' (string)
true

Finding non-admins:

'not 1' (string)


Index "Column A" for unique values, then recursively group "Column B" values based on those uniques

Possible, yes. But if you should do it with Twig alone is a totally different thing. There's other ways to do that in Craft,
e.g. with relations (Entries Fields) and splitting your Products and their variants into separate sections. Or what about using a structure,
with your variants being child entries to the product?

But here's how you do that with your table field (totally legitimate in my opinion, one advantage being the ease of use for the Client):

{# Prepare variable before loop #}
{% set myVariants = [] %}

{% for row in myTableField %}

    {# Concatenate a string to the value to prevent it from being numeric #}
    {% set variantKey = 'key' ~ row.col1 %}

    {% if variantKey not in myVariants|keys %}

        {# Insert a new key and add the first value to it #}
        {% set myVariants = myVariants|merge({ (variantKey): [row.col2] }) %}

    {% else %}

        {# The key already exists, so merge the value to the existing ones #}
        {% set myVariants = myVariants|merge({ (variantKey): myVariants[variantKey]|merge([row.col2]) }) %}

    {% endif %}

{% endfor %}

This is how you print it:

    {% for variantKey, variantsLevel1 in myVariants %}

            {# Remove the string from our key again #}
            {{ variantKey|slice(3) }}

                {% for variantLevel2 in variantsLevel1 %}

{{ variantLevel2 }}

                {% endfor %}

    {% endfor %}


How do I output only country part of location field using the SimpleMap plugin?

Never used the plugin, but from the docs:

parts
This contains the locations address, broken down into its constituent parts. All values are optional so you'll need to have checks on any you use to make sure they exist.
A list of the available values can be found here.
To access the short version of any part, append _short to the end of its name. E.g. {{ myMapField.country_short }}.

Sounds like the country info is optional and may not exist on the model, hence the note to check if it exists or not first.
i.e.
{% if myMapField.country_short is defined %}
    {{ myMapField.country_short }}
{% endif %}


Form Builder plugin returns 'undefined' when I submit

we ran into the same problem. If you remove "admin" on line 12 of /plugins/formbuilder/resources/js/formbuilder-form.js it works.

url = '/actions/' + $(this).children('[name=action]').attr('value');

We couldn't figure out why the path leads to something which is only accessible with admin-rights.


I realize that this is an older question, but I have found the answer for it after much searching, and want to leave this answer for others who might be coming from a search engine.

The way I have found that you would do this is with the Stripe Payments plugin. The documentation for it can be found at https://github.com/craftcms/commerce-stripe.

From there, you will find that there is a beforeSubscribe event. You can use that to set parameters for quantity. From the documentation:

use craft\commerce\stripe\events\SubscriptionRequestEvent;
use craft\commerce\stripe\base\SubscriptionGateway as StripeGateway;
use yii\base\Event;

Event::on(StripeGateway::class, StripeGateway::EVENT_BEFORE_SUBSCRIBE, function(SubscriptionRequestEvent $e) {
    $e->parameters['someKey'] = 'some value';
    unset($e->parameters['unneededKey']);
});

For my subscription, I have found that $e->parameters['items'][0]['quantity'] = 3; works for my setup.


I can't think of a non-terribly hacky way to pull this off in the current version of Craft, unfortunately.

You might want to consider adding a thumbs-up/comment to this feature request that would allow for what you're looking for: https://github.com/craftcms/cms/issues/947


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

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

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

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

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


Limit search results for users by tag (and limit to 5 tags)

There’s no way to tell the relatedTo param to only factor in the first X relations per source element (the first 5 tags per user, in this case).

I can think of two ways you could accomplish this:

Option 1: Use two Specialism fields

Replace your “Specialism” Tags field with two Categories fields – “Primary Specialism” and “Secondary Specialism”. Limit “Primary” to 5 categories, so no one can ever enter more than 5 specialties in there, and they can list any additional specialties  in the “Secondary” field.

Then from your template, you can limit the search query to only factor in the “Primary” field:

{% set results = craft.users({
    group: 'verified',
    relatedTo: {
        targetElement: craft.categories({
            group: 'specialisms',
            search: query
        }),
        field: 'primarySpecialism'
    }
%}

This method will get more complicated if you do start allowing premium members to be found from both fields down the road; you would need to split it up into two separate user queries – first for the premium members, and then again for the normal members.

Option 2: Automatically store the searchable specialisms in a separate, hidden field

Install the excellent Preparse plugin, and create a new Preparse field called “Searchable Specialisms” with the following Twig code:

{% spaceless %}
    {% for tag in user.specialismTags.limit(5) %}
        {{ tag.title }}
    {% endfor %}
{% endspaceless %}

(Disable the “Show Field” setting so this field doesn’t show up on user profile pages. {% spaceless %} is required to remove initial whitespace character from the newly parsed “Searchable Specialisms” field)

Once the field is created, add it to your User field layout (Settings > Users > Fields) - doesn’t matter where.

Finally, update your set results template code to this:

{% set results = craft.users({
    group: 'verified',
    search: 'searchableSpecialisms:"' ~ query ~ '"'
}) %}

This approach will make it much easier to handle the premium member feature down the road, because you’ll just need to factor in whether they are a premium member or not in the Preparse field settings:

{% set limit = user.isInGroup('premium') ? null : 5 %}
{% for tag in user.specialismTags.limit(limit) %}
    {{ tag.title }}
{% endfor %}


How to set error message in element action?

I know this is a late reply. I hope it will help others.

You need to return false; so that the background color is red.

Example:

     if (count($criteria->ids()) > 1)
     {
         $this->setMessage($this->getParams()->warningMessage);

         return false;
     }


8-bit png's get distorted when you upload them

The fix for distorted 8bit png's is to install imagick on the server.

I'm running whm/cpanel and there were some hoops to jump through to get it installed. I installed it in terminal and then in WHM, I had to enable it for PHP.


Date fields in Craft are returned as DateTime objects, so you need to convert these to a string to be able to compare them.
The best way of doing this is to use the yyyy-mm-dd format as this makes it is easy to compare dates.
So your comparison would become:
   {% if (entry.dateUpdated|date('Y-m-d')) >= (entry.postDate|date('Y-m-d')) %}
      Updated on {{ entry.dateUpdated.format('j M y') }}
   {% endif %}


Navigation position in Control Panel Craft CMS 2.5

I wouldn't have thought so, it's to facilitate the new Commerce plugin (or at least that was the main driver) and ultimately is far more expandable over time.

The new interface is fluid too, rather than the previous fixed version. It took a little while to get used to but is now much better suited to the content input.


At the most simple level, if you have a Notification Email configured with the event 'None', you can do the following:

$mailer = SproutBaseEmail::$app->mailers->getMailerByName(DefaultMailer::class);
$notificationEmail = Craft::$app->elements->getElementById(123);
$mailer->sendNotificationEmail($notificationEmail);

If you have an Event selected other than 'None' or want to use any Personalization in your email, you may need to also configure the notification to have the Event Object.

Let's say, your Notification Email body needs to use the person's name:

Hello {firstName}

OR

Hello {{ object.firstName }}

In that case, you can use the setEventObject method to set any variables you need available in your Email Template:

$mailer = SproutBaseEmail::$app->mailers->getMailerByName(DefaultMailer::class);
$notificationEmail = Craft::$app->elements->getElementById(123);
$notificationEmail->setEventObject([
  'firstName' => 'Mr. Smithyyy'
]);
$mailer->sendNotificationEmail($notificationEmail);


Auto-populate login form when accessed via client intranet

Couldn't you set the password to a variable on the login page if it is the correct intranet url?

{% if craft.request.getUrl() == "intranet.net" %}
 {% set pass = "password" %}
{% endif %}

<input type="password" value="{{ pass|default('') }} name="password" />


How to develop plugin/module to build landingpage upon fetched JSON-data

I'd make a template called landing that would have various entries/entry types in it where I can add whatever CMS content I want.

https://www.example.com/landing/landing-page-slug

For a nice content authoring experience, I'd make a custom Element that knows to go out over the wire and fetch the data from the Laravel database via whatever JSON endpoint you've set up in your Laravel app, and a custom Field that is just a simple ElementSelect for my custom Element.

That way in your Craft CMS entry, you could just click a button to browse the various rows in your remote Laravel db (presenting the information in a nice UI that'd look exactly like you're selecting another Craft entry).

Then on the templating side of things, it'd work like anything else does in Craft. Through the custom Element, you'd have access to all of the data from your remote Laravel db table, e.g.:

{{ entry.laravelData.someField }}

Bonus points would be awarded for a nice caching layer to keep things performant.


Site URL displays "Page Not Found The requested URL was not found on this server." but the backend loads fine

Got it working! Not really sure exactly what was causing it, but it seems to have had something to do with my Capistrano setup not craft or Apache.


Checking if a value is in an array of IDS - using a filter?

You could use filter to get only the variant that matches the wheelSpacer variable. This will return an array, so you can use first to get the first matching variant (since presumably product.variants won't contain duplicate variants). This has the added benefit of getting you the matching variant directly, instead of it's ID:
{% set variant = product.variants|filter(variant => variant.id == wheelSpacer)|first %}
{% if variant %}
    {# ... #}
{% endif %}

As a sidenote, if your variants field is an Entries field, you'll want to use product.variants.all() instead.


How to skip the first X entries using ElementAPI

It seems that offset doesn't work when pagination is set to true (which is its default value).

If you don't need pagination for your results, you can add your offset in criteria and set pagination to false.

If you do need pagination and the desired offset is the same as elementsPerPage, you can get your results starting from page 2. You'll have to make sure you're actually getting page 2 because it will return page 1 if there aren't enough results for a second page.

If you do need pagination and the desired offset is different from elementsPerPage, you can try what I've done here.

'stories.json' => function() {
    // Get get IDs of the "offset" entries. Set `limit` to the offset amount you want.
    $excludedIds = Entry::find()
        ->section('stories')
        ->limit(4)
        ->ids();

    // Form value for id in criteria to exclude the above entries.
    $criteriaId = count($excludedIds) ? ('and, not ' . implode(', not ', $excludedIds)) : null;

    return [
        'elementType' => Entry::class,
        'criteria' => [
            'section' => 'stories',
            'id' => $criteriaId,
        ],
        'pretty' => true,
        'elementsPerPage' => 6,
        'transformer' => function(Entry $entry) {
            return [
                'title' => $entry->title,
                'url' => $entry->url,
                'id' => $entry->id,
            ];
        },
    ];
},

I found that you can still paginate results with a value for id set in criteria. So, I've excluded the IDs of the offset entries and paginated the results with those entries removed.

I've also made an issue on the Element API Github repo to see if there's a better solution:
https://github.com/craftcms/element-api/issues/99


Error when rendering a template (for HTML email) on users.saveUser

The issue turned out to be the result of a variable name mistake on my part. I had typed in an incorrect variable name in the email template. I actually still don't really understand what that has to do with a database transaction, though.

EDIT:
If anyone else is running into a similar issue, I've found a way to get a more useful error message, as opposed to the "CDbTransaction is inactive" message, which doesn't help much. If you go to craft/app/services/UsersService.php, and comment out line 311 ("$transaction->rollback();"), then Yii won't give you the CDbTransaction error before Craft has a chance to tell you its more helpful error. This should give you a better idea of what you're doing wrong. Obviously, don't forget to un-comment that line after you've fixed your issue.


Update:
Craft 3 officially supports MariaDB 5.5+ now. https://docs.craftcms.com/v3/requirements.html

Not officially, no.  MariaDB is supposed to a "drop-in" replacement for MySQL, but there are clearly areas where it is not 1:1 compatible with MySQL: https://mariadb.com/kb/en/mariadb/mariadb-vs-mysql-compatibility/

We've seen some installations using MariaDB where a query would actually return incorrect results and the same MySQL query on the same database returns that data correctly.


How do I enable redactor rich text editor in a front-end form?

It’s technically possible to include Craft’s copy of Redactor on the front end:

{% includeJsResource "lib/redactor/redactor.js" %}
{% includeCssResource "lib/redactor/redactor.css" %}

<textarea id="jobOverview" name="fields[jobOverview]"></textarea>
{% includeJs "$('#jobOverview').redactor();" %}
...

But it’s not recommended. Redactor’s API and config settings frequently change, and we generally try to keep it updated with each new Craft version. If you started including Craft’s version of Redactor, you’re going to have to start testing your website to make sure your front-end Redactor fields are still working properly each time you update Craft to a new version.

(I’m also not sure about the legal implications. Craft comes with a Developer license of Redactor which gives us unlimited use of it, but whether or not end users of Craft are allowed to use it is a gray area you should check with Imperavi on.)

You’ll be better off in the long run by grabbing your own copy of Redactor and installing it yourself for the front end site.

Update:

We checked with Imperavi and the Developer license we purchased for Craft is allowed to be used on the front and back-end of Craft, although we still don't recommend it for the reasons listed above.


How do I create database tables for a craft cms plugin on install?

PluginNameRecord.php is how Craft installs database tables. You can also have multiple tables by using PluginName_TableRecord.php where 'Table' will be the name of the new table in the database.

Might also be worthwhile to mention that the cocktails recipe you linked to has a lot of issues as it has not been updated for the latest versions of Craft.

Sean Delaney updated that plugin and the new repository is here:

https://github.com/seandelaney/cocktailrecipes


Laravel Homestead & Craft: Craft can’t connect to the database with the credentials in craft/config/db.php

When in doubt, reinstall, or in this case do it over again from the top. That fixed it.


Updating an entry after an event action within onSaveEntry

Use craft()->elements->saveElement the second time. It will work exactly the same but won't trigger the onSaveEntry event.


Try passing your relatedTo parameters as an array:

{% set members = craft.users.group('members').relatedTo([ 'and', { targetElement: services }, { targetElement: locations } ]) %}

or a little easier to read:

{% set entries = craft.users({
    group: 'members',
    relatedTo: [
        'and',
        { targetElement: services },
        { targetElement: locations }
    ]
}) %}

Edit:

If you want to get only those users that are related to both services, add another relation to your parameter array:

{% set service1 = craft.categories.group('services').slug('service-1') %}
{% set service2 = craft.categories.group('services').slug('service-2') %}
{% set locations = craft.categories.group('locations').slug('location-1') %}

{% set entries = craft.users({
    group: 'members',
    relatedTo: [
        'and',
        { targetElement: service1 },
        { targetElement: service2 },
        { targetElement: locations }
    ]
}) %}

Update:
(Copied the solution from Sean's other question, because it also fits here!)

If you need to add those relations programatically, that's how I would do it:

{# Compose the relation param #}
{% set relationParam = ['and'] %}

{# Add to the relation param #}
{% if condition1 %}
    {% set service1 = craft.categories.group('services').slug('service-1') %}
    {% set relationParam = relationParam|merge([{ targetElement: service1 }]) %}
{% endif %}

{% if condition2 %}
    {% set service2 = craft.categories.group('services').slug('service-2') %}
    {% set relationParam = relationParam|merge([{ targetElement: service2 }]) %}
{% endif %}

{# Get users of group "member" #}
{% set users = craft.users.group('members') %}

{# Further filter users - avoid passing an array with `['and']` only #}
{% if relationParam|length > 1 %}
    {% set users = users.relatedTo(relationParam) %}
{% endif %}


How can I set shipping address same as billing?

Unfortunately, I found myself in the exact same situation.

What I ended up doing was including both the billing and shipping form on the same page but the billing form hidden. I used vue.js form/model binding to ensure the values were copied to the billing form. This way it captures two identical addresses, but at least they have the opportunity to edit the information separately at final checkout if shipping is required.


craft()->cache can point to different places, depending on what the cacheMethod config setting is set to.

By default, it's set to file, which means that your cache will be saved to the file system in the craft/runtime/storage/cache folder.

So you can pretty much save as much there as you have disk space available.

Just keep in mind, if you're saving something that's 500MB worth of text, PHP is roughly going need 500MB worth of extra memory to be able to read and write that data.


Passing true as the second parameter to print_r returns a string that can be written to the log.

Plugin::log(print_r(array('test'), true));


entry.getAuthor().getGroups() always return empty array

I spot a couple of Twig errors in your code.

First, in your for loop you're casting the entries returned by craft.entries to a variable news, but you're calling entry.getAuthor() inside the loop. Either change news to entry or entry to news.

Second, I'm not sure if craft.entries('news') actually returns anything (or at least not what you actually want) – it should probably be craft.entries.section('news').

Putting it together, this should work:

{% for entry in craft.entries.section('news') %}
    ...
    {{ dump(entry.getAuthor().getGroups()) }}
{% endfor %}

Also, since you're not reporting any error messages output by Craft, I'm guessing you haven't enabled devMode in your development environment. It's a really good idea to have devMode set to true while you're working on your code, because then Craft will report any syntax errors (like your undeclared entry variable) which will make it way easier for you to debug.

Just remember to never have devMode enabled for production environments – it's both a performance and security issue if you do.


How might big Matrix/Relationship fields affect front-end CP performance?

Matrix fields are going to suffer from similar scalability issues if you have a large number of blocks in a single field, affecting memory consumption, MySQL/Javascript performance, and usability. We consider that a bug (and it has been logged in our bug tracker as such), and plan on addressing it at some point in the future.

Relational fields have similar issues if you plan on selecting hundreds of elements. If you simply have a section with hundreds of entries, but don’t intend on actually selecting more than a handful, you don’t have anything to worry about; the element selector modal that comes up when you want to select additional elements is perfectly scalable, because it only loads 50 elements at a time, and lazy-loads additional elements as needed via an infinite scrolling implementation.


Is there a good way to eager load Craft's Element Relations through a plugin?

I wanted to do this too but none of the relationships are defined in the record classes.

An approach to achieving this would be to extend the Craft record classes in your own record classes and override the defineRelations method. This does however require that you understand CActiveRecord relations.

If you need any pointers give me a hollar.


The Definitive Guide to Extending Twig in Craft CMS

To encourage input, this is a community wiki post. Any user with at least 100 reputation points may contribute.

Functions, filters, objects, macros and statements – when to use which

A function is one of the simplest constructs in Twig – it takes one or more inputs and returns a single output:

{{ round(42.9) }} will output 43

These are best used for simple, commonly used operations that generate or transform data, such as a Lorem-Ipsum generator: {{ loremIpsum(50) }}. But note that functions are often better grouped into an object to prevent name collisions (see below).

A filter is almost identical to a function, except that it offers a different syntax, which can be more readable when chaining several filters together (they read in progressive order):

{{ 1000000 | number }} will output 1,000,000
{{ 1000000 | number(false) }} will output 1000000
{{ 'ABC' | lower | replace('c', 'd') }} will output abd

It also provides an easy way to wrap around a larger block of text:

{% filter upper %}
    This text becomes uppercase
{% endfilter %}

Note that you can also do this with a function, but it requires an additional line:

{% set myText %}
    A quick brown fox
{% endset %}
{{ filterCurseWords(myText) }}

Use a filter when:

It might be necessary to place it in a chain along with other filters
It might be necessary to place around larger blocks of text/content

A global variable is one accessible to all templates in your project automatically:

{{ siteName }}

A global object is also accessible to all templates in your project, but can contain variables, functions or both:

{{ currentUser.friendlyName }}
{{ currentUser.can('accessCp') }}

Objects provide a good way to neatly group variables and functions and prevent collisions.

A Twig statement (sometimes called a "logic tag") is used to designate the flow of logic and may only execute the content inside based on certain circumstances.

{% cache %}
    {% for block in entry.myMatrixField %}

{{ block.text }}

    {% endfor %}
{% endcache %}

Note that caching would not work as a filter, because the content inside a filter is always executed prior to being passed into the filter. By implementing the cache tag as a statement, it is able to only execute the content inside when appropriate.

Finally, it's worth mentioning macros. They assist with reusing snippets of content or HTML in multiple places. Mijingo has written a great tutorial that explains macros in Craft.

{% import "forms.html" as forms %}
{{ forms.input('username') }}

Note, however, that the functionality of macros can sometimes be replicated via a simple include, with less code and more clarity:

{% include 'mySnippet' with { enabled: true } %}

Creating a custom Twig filter

{{ myVariable | myFilter }}

More content to come here. Feel free to contribute some instructions if you're able.

Accessing a plugin's variables and functions

{{ craft.myPlugin.myVariable }}
{{ craft.myPlugin.myFunction() }}

More content to come here. Feel free to contribute some instructions if you're able.

Creating a custom global function

{{ customFunction() }}

More content to come here. Feel free to contribute some instructions if you're able.

Creating a custom global object

{{ browser.version }}
{{ browser.isMobile() }}

More content to come here. Feel free to contribute some instructions if you're able.

Creating a custom statement (logic tag)

{% devOnly %}
    ...output some debugging info here...
{% endDevOnly %}

Refer to http://twig.sensiolabs.org/doc/2.x/advanced.html#tags

More content to come here. Feel free to contribute some instructions if you're able.

Be aware that sometimes the functionality can be achieved by creating a filter instead of a statement:

{% filter uppercase %}
    A quick brown fox
{% endfilter %}

However the benefit of a statement is that the code inside is not run unless the statement permits it, whereas in a filter the code is always run, and then later sent to the filter.

Creating a custom operator

{{ ! true }}

Refer to http://twig.sensiolabs.org/doc/2.x/advanced.html#operators

More content to come here. Feel free to contribute some instructions if you're able.

Calling a plugin service class from Twig

Under normal circumstances, Twig templates only have access to a plugins Variable Classes and not their Service Classes. But using a simple PHP trick, you can pass all calls on transparently:

Twig > Variable Class > Service Class

// craft/plugins/YourPlugin/variables/YourPluginVariable.php
class YourPluginVariable
{
    /**
     * If function is not found in this class, go find it in service class
     */
    function __call($method, $arguments) {
        return call_user_func_array(array(craft()->YourPlugin_YourService, $method), $arguments);
    }
}

Be sure to rename YourPlugin and YourService to reflect the names of your plugin and service class.

Making custom database calls from Twig

{{ craft.myPlugin.fetchUserCount() }}

Firstly this requires a custom plugin.

In Craft, database calls need to be made via a service class, however because you can only access variable classes from Twig, you need to pass one to the other. (See the point above for a clean way to transparently pass calls from a variable class to a service class.)

Twig > Variable Class > Service Class > Database Query

More content to come here. Feel free to contribute some instructions if you're able.

Post-processing HTML after Twig has finished rendering

More content to come here. Feel free to contribute some instructions if you're able.

Changing Twig settings

More content to come here. Feel free to contribute some instructions if you're able.


Here is one: https://medium.com/good-dog/deploying-craft-cms-to-amazon-ec2-running-the-lemp-stack-using-mina-e2ad955138fa#.54s4y29co

Disclaimer: I work for the company that published this.


You have some other bug somewhere else. Check the code pulling out entry details to be sure that it doesn't modify loop or the list you are looping on, or the current item.

This code works:

{% for item in (1..10) %}
  {% if loop.first %} [ {% endif %}
  {{ item }}
  {% if loop.index is divisible by(4) and not loop.last %}
    ] [
  {% endif %}
  {% if loop.last %} ] {% endif %}
{% endfor %}

And outputs this:

[ 1 2 3 4 ] [ 5 6 7 8 ] [ 9 10 ]

You can simplify it a bit:

{% for item in (1..10) %}
  {% if loop.first %} [ {% endif %}
  {{ item }}
  {% if loop.index is divisible by(4) or loop.last %}
    ] [
  {% endif %}
{% endfor %}

You also can use the batch filter, which I think makes things slightly clearer:

{% for b in (1..10) | batch(4) %}
  [
    {% for item in b %}
      {{ item }}
    {% endfor %}
  ]
{% endfor %}


Localization - linking to other pages goes to 404

First off, make sure you have .htaccess files in both the en and fr folders and this per the localization guide.

Secondly, you're missing a comma in the siteUrl array:

'siteUrl' => array(
    'en' => 'http://etf-craft.dev/en/',
    'fr' => 'http://etf-craft.dev/fr/' <--------add comma here-----
),


Sounds like a fun project. :) My thoughts:

– I'd ditch using Commerce' stock management, and set all products to have unlimited stock.

– I'd build a plugin that has a field type that attaches to products/variants, that lets the client add stock to certain dates for that product/variant.

– I'd have template variable for getting stock for a given date and product/variant, and use it to show availability in the templates. If you need to show availability in product listings, I'd probably also create a custom template variable for getting products (instead of using craft.commerce.products directly), that extends the element criteria to add your custom stock availability to it (see this article, or my Similar plugin for examples).

– I'd listen for some Commerce events (commerce_orders.beforeOrderComplete and commerce_variants.onOrderVariant) to update the stock level when an order is placed (see the Stock Notifier plugin from P&T for examples)

To be honest, I think the biggest challenge is the second point, making the interface and database structure that lets the client update availability. A real simple solution where they add a date and a number for stock, is easy enough. But making a nicer calendar interface, and adding support for stuff like recurring dates ("we have 20 fresh cinnamon rolls every thursday"), gets pretty complicated pretty fast. But, it all depends on the use case how advanced it needs to be.

Anyways, that's my initial thoughts. :)


Craft Commerce: How do I handle quantity based discounts on a product level?

Have you looked into building an adjuster for this purpose? You can find the documentation here


CP not loading on Forge Server with PHP 7

2015/12/09 15:42:38 [error] [exception.Error] Error: Class 'Twig_Cache_Filesystem' not found in /home/forge/staging.domain.com/releases/20151209154140/craft/app/vendor/twig/twig/lib/Twig/Environment.php:263

That indicates that Craft is missing some of its files.  Try re-uploading your craft/app folder with a fresh copy downloaded from https://craftcms.com.


You could create a matrix content field for the homepage with a child entry selection field. You can add as many matrix blocks as you'd like, and select the entries you would like within them.

You can read more about Matrix fields here.

Likewise you can checkout entry field types here.

So your code for index.twig might look like:

{% for block in entry.calloutBlocks %}

    {{block.title}}
    {{block.body}}
    Read more

{% endfor %}


How to process CSV files within a Matrix field?

You're not overlooking anything. What you're asking for is not a core feature of Craft and probably will never be. There's also no plugin yet that does something like this.

So the only answer I can give you right now is that you have to find someone who makes such a plugin for you. The jobs board on straightupcraft.com is probably a good address to find a developer.


Turns out it needs the space in the conditional either side of the vertical bar so the code should’ve been:

{% if block.destination | length > 25 %}
{% endif %} {{ block.smallCost }}


Comparing 2 versions of an entry and highlighting the changes

That's currently not a native feature in Craft, but you might want to consider voting for this similar feature request.

You could pull it off with a custom plugin in the meantime, too.  Since entry revisions are stored between saves, you'd need to pull that revision data from the database using the EntryRevisionsService, add the business logic for calculating the diffs and come up with a UI for displaying it.


Entry saving in task fails due to required assets/matrix fields being read as blank, even through they are not

This is due to the way Craft manages custom fields at the moment (but has been “fixed” for Craft 3). Whenever you save an element, you need to make sure all of the field values are in the same format they would be if they had come from an Edit Entry form submission. Here’s another post that describes what that looks like: How to save a matrix content of a new entry in my plugin?


Although your question is lacking in detail, here is a shot at helping you track down the issue. The fact that GET requests are working but POST requests are not, your form is likely missing a CSRF token. You can add it to your form using the following twig code:

<form method="post" action="">

   {{ csrfInput() }}

If your POST request is coming through as an AJAX request then you can create and submit a CSRF token as described in this answer.


Pagination with if statement date modify

You can add it like every other criteria property

craft.entries.date('>' ~ now|date_modify('-1 day')|atom)


Update Error: Could not validate update handle

Looks like the issue had to do with my production environment being load-balanced. To avoid errors like these on load balanced sites, remember to set the validationKey and appId config keys in your general.php file.


Is it possible to take an excerpt from the first rich text area in a matrix?

You can filter by block type: http://buildwithcraft.com/docs/matrix-fields#filtering-by-block-type

In short:

{% set ogDescription = false %}

{% for block in entry.myMatrixField.type('richText').limit(1) %}
  {% set ogDescription = block.text | striptags | slice(0, 155) %}
{% endfor %}

{% if ogDescription %}
  ...
{% endif %}

Also, this was suggested in the comments:

{{ entry.myMatrixField.type('richText').first() | striptags | slice(0, 155) }}


You are correct, purchase total is the total of items selected.

We will look to add a 'Total Order Price' condition in the future.

For now you would need to make your own custom discount adjuster to build special discount conditions.


Is there a way to prevent uploading assets into a parent level folder?

The only way I know how to do this would be to create a different asset channel for each child directory.


How would I create unique fields for different user groups programmatically?

You could control which fields a user has access to based on their group from a front end edit profile page, but there is no way to do this in the admin outside of creating a plugin with a custom table and screens.


JQuery $.ajax ":success" form logic with Plugin Controller?

The issue was that curl was, by default, returning the result of the http request to the WebToLead servlet directly, rather than only storing it as $result. This raw HTML response was super-ceding the returnJson() response, resulting in an error in jQuery's ajax function.

To force PHP curl to echo the result rather than return it, you need to set a curl option for CURLOPT_RETURNTRANSFER to true. Revised as such:

// Set the url, number of POST vars, POST data
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE  );
curl_setopt($ch, CURLOPT_POST, count($kv));
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);

This returns just the JSON response from the function in Craft's baseController, and therefore a successful response to jQuery.


First, you'll want to make sure you're on the latest FeedMe release as a bug around this was recently fixed: https://github.com/craftcms/feed-me/issues/694
You might also need a plugin that hooks into the EVENT_AFTER_FETCH_FEED event to do some offset transformation based on the tokens passed in.


I've contacted Freeforms (Solspace). Unfortunately there is no solution for this problem (yet). Solspace told me:

  This functionality currently isn't possible with Freeform. It's something on our feature requests list though.


Intercepting Sprout Forms "onSaveEntry" Event In Craft 3 Plugin

I've updated the Sprout docs with examples of Craft 3 events and hooks.

In your case, the Form Entry Element extends the craft\base\Element class and also supports the same after the base element save event: EVENT_AFTER_SAVE. In your primary plugin class init method:

use barrelstrength\sproutforms\elements\Entry;
use yii\base\Event;
use Craft;

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

    Event::on(Entry::class, Entry::EVENT_AFTER_SAVE, function(Event $event) {
        if (Craft::$app->request->isSiteRequest)
        {
            // A Form Entry Element has been saved from a Front-end Form Submission
            Craft::dd($event->sender);
        }

        if (Craft::$app->request->isCpRequest)
        {
            // A Form Entry Element has been updated from the Control Panel

            Craft::dd($event->sender);
        }
    });
}

You can access the specific Form Entry Element being submitted via the $event->sender property.


What is the best way to track, record or view search terms?

We track search terms on buildwithcraft.com the same way we track all other site activity: using Google Analytics.

All you have to do is throw GA event tracking code into your search results template.

If you’ve upgraded to Universal Analytics/analytics.js, use this:

{% set js %}
    ga('send', 'event', 'Search', 'Search', '{{ query|e("js") }}', {'nonInteraction': 1});
{% endset %}
{% includeJs js %}

If you’re still on the old ga.js, use this:

{% set js %}
    _gaq.push(['_trackEvent', 'Search', 'Search', '{{ query|e("js") }}', null, true]);
{% endset %}
{% includeJs js %}

There are other ways to include the JS, of course. (In our case we actually have a blank analytics block right alongside other Google Analytics instantiating code in the layout template, and set this JS code by overriding that block on templates that have custom things to track.) This {% includeJs %} route is just the most unassuming.

With that code in place, you’ll be able to start tracking “Search” events from Behavior > Events in your Google Analytics dashboard.


How can I get the requested entry from a plugin?

You can get the request’s matched element via:

$element = craft()->urlManager->getMatchedElement();

There are two things to remember though:

There may not be a matched element
The matched element might not be an entry. (It could also be a category, and if you have any plugins installed that add their own element types that can have their own URLs, it could be one of those.)

To defend against those possibilities, just use the following conditional:

if ($element && $element->getElementType() == ElementType::Entry)
{
    // There was a matched element, and it's an entry!
    // ...
}


Display tag related to entry in current locale

As pointed out in the comments to your question, there's no need
to specify the locale with your relatedTo parameter.

I already wrote you in response to your other question, Craft always works in one locale
only if you don't explicitly make it to do otherwise.

{% for entry in entries %}

{{ entry.title }}

    {% for tag in craft.tags.relatedTo(entry) %}

        {{ loop.first ? '
' }}

{{ tag.title }}

        {{ loop.last ? '
' }}

    {% else %}

No tags found

    {% endfor %}

{% endfor %}


I'm not sure how dynamic you need this to be. One way would be to set an order of classes to loop through with Tiwg's Cycle function. This would go through each class in the array, in a cycle.

{% set classes = ['full-wide', 'third-wide', 'third-wide', 'third-wide', 'half-wide', 'half-wide'] %}

{% for entry in entries %}
    <div class="{{ cycle(classes, loop.index0) }}">
        {# output entry #}
    </div>
{% endfor %}

If you need a bit more flexibility you could use conditionals querying the loop variable to determine where you are in the output.


Redactor 2 - Can a text alignment button be added?

You can use the formattingAdd config setting to add custom formatting to the "Format" dropdown.

formattingAdd: {
  "align-left": {
    "title": "Align left",
    "args": ["p","class","align-left"],
  },
  "align-right": {
    "title": "Align right",
    "args": ["p","class","align-right"],
  },
  "align-center": {
    "title": "Align center",
    "args": ["p","class","align-center"],
  },
  "align-justify": {
    "title": "Justify",
    "args": ["p","class","align-justify"],
  },
},

If you want to have a separate dropdown or individual buttons in the toolbar for this functionality, have a look at my plugin Redactor Inline Styles.


Modifying Commerce line items after order is complete

I found a solution (possibly temporary) to my problem. Instead of trying to modify the line items via the order itself, I am modifying them directly.

After changing the line item during the for loop, I pass the $item variable back into this code:

craft()->commerce_lineItems->saveLineItem($item);

I'm not entirely sure what the extra impact that is on the number of queries, but considering that most people will only order a single gift card, maybe two, I would imagine that it's not a terrible way to accomplish this.

I'm still open to ideas of a better way to solve my issue, but for now it seems to do the trick.


Check out the Retcon plugin!

  Retcon is a small Craft CMS plugin offering a series of easy-to-use Twig filters for manipulating HTML content.

Specifically, it sounds like you need the wrap method:

{{ entry.body|retconWrap('iframe', '.videoWrapper') }}


Craft Commerce: Filter completed orders based on a product category field

Managed to solve this.
First, I've added a categories field to the order form.
On the checkout page I loop over all lineItems in the cart and collect the category id's like this.
{% set categoryIds = [] %}

{% for item in cart.lineItems %}
  {% set categories = item.purchasable.product.productGroup.leaves().all()%}
  {% for category in categories %}
    {% if category.id not in categoryIds %}
      {% set categoryIds = categoryIds|merge([category.id]) %}
    {% endif %}
  {% endfor %}
{% endfor %}

Then, I submit the categories using a hidden input.
{% for catId in categoryIds %}
  <input type="hidden" name="fields[productGroup][]" value="{{ catId }}">
{% endfor %}

Now I have categories assigned to an order and can easily filter them using .relatedTo(), like this:
{% set ordersQuery = craft.orders().relatedTo(...) %}


Craft 3 image asset getUrl() not showing

The solution is to enable "assets for this source have public URLs" in the volume settings.


Is it possible to setRouteVariables when redirecting after a successful form submission?

Other than the query string, you're options are:

Save it to a cookie and retrieve it from the next page with something like this plugin.
Save it to cache (craft()->cache).
Save it to PHP's $_SESSION, which Craft wraps with HttpSessionService (craft()->httpSession).
Writing a plugin with a Twig function that wraps Craft's craft()->userSession->setFlash() method, which will store a key->value pair in session for exactly one request. You can retrieve the value via craft.userSession.getFlash().

Note that there are limitations to the size and complexity of the data you can pass along with all of these and in almost all cases, the data needs to be serializable.


How to manage breakpoint releases when updating Craft via composer

So far, Craft 3 hasn’t had any “real” breakpoint releases in the way that Craft 1 and 2 had, yet – where you would have a real issue if you were to update past them before updating to them.

Craft 1 and 2 had a handful of them, which we took as opportunities to clear out the migrations/ folder, and clean up some PHP code. If you were to (somehow) update past one in Craft 1/2, Craft would actually stop you in your tracks before you were able to run migrations, and tell you to downgrade to the breakpoint your skipped first.

If/when we release a real breakpoint release in Craft 3, Craft will do the same.

To date, Craft 3 has only had 2 “faux” breakpoints:

When updating from > 3.0.0-alpha.1 && < 3.0.41.1, the built-in updater will have you update to 3.0.41.1 before going past it. This is because Craft 3.1 was a pretty huge update that revealed some bugs in the 3.0 updater. So 3.0.41.1 was released with some fixes to the updater, to ensure people could update to 3.1 more gracefully. Not an issue if you were using composer update to update though.
When updating from >= 3.1.20 && < 3.1.34.3, the built-in updater will have you update to 3.1.34.3 before going past it. This is because there were a couple bugs in the project-config/rebuild command (added in 3.1.20) that we fixed in 3.1.34.3 which could create trouble for the 3.2 update, had the command been used. So adding the faux breakpoint combined with a suggestion in the 3.2 release notes to re-run project-config/rebuild was just a way to reduce potential support for 3.2 updates. If you were to composer update without following those directions, either the 3.2 update would work or it wouldn’t; in the latter case we’d end up steering you right in support.

Regarding plugins, we don’t currently offer support for plugin breakpoints, and aren’t very likely to add it, unless a really good use case comes up.


Can someone help me with my site structure? Sections/Category setup

It's fairly straight forward. You could go with a single "layout" file and then a template file for each unique template that utilizes that simple header/footer layout

templates/layouts/_layout.html
templates/index.html (homepage)
templates/products.html
templates/support.html
templates/contact.html

Extending a layout:

{% extends "layouts/_layout" %}

Your product template would then just need to be coded to handle the category handle in the URL.

For instance, listing entries (products) that are assigned to a category (untested):

{# get categorySlug from URL segment 2 #}
{% set category = craft.request.getSegment(2) %}

{# get instance of category #}
{% set category = craft.categories.slug('categorySlug') %}

{# get entries related to the category instance #}
{% set entries = craft.entries.relatedTo(category) %}

{# loop through the entries #}
{% for entry in entries %}
    {{ entry.title }}
{% endfor %}

That's obviously just an example, but should get you going in the right direction.

Related reading material:

https://craftcms.com/docs/templating/craft.request#getSegments


internal_error.html isn't a file that is shipped with Craft.

Most likely what is happening is that you're running into some fatal PHP error (like bumping into your php.ini file's memory_limit or max_execution_time setting) and your host has configured all fatal errors (or anything with a 500 Internal Server Error response code) to redirect to their internal_error.html template.

Craft doesn't know how to route to that template, so you get the error above.

I'd check Craft's logs at craft/storage/logs and/or your web server's error logs for the real underlying error.


using cycle with unknown number of entries

Maybe you can use Twig's batch for this?

Twig Batch

{% set items = ['a', 'b', 'c', 'd', 'e', 'f', 'g'] %}
{% for row in items|batch(3, '') %}

    {% for column in row %}

{{ column }}

    {% endfor %}

{% endfor %}

Batch lets you have something to fall back on when you have less items. In this case there are 3 items within my row and if there will be 2, it will output what I have in the '', in this case nothing. (but I can put what I want in that '').


How can I return the entry with the highest value?

Sounds like you're looking for a combination of the orderBy and relatedTo entry query params.

This may put you on the right track?

{% set topThree = craft.entries({
  section: 'posts',
  relatedTo: { targetElement: myCategory },
  orderBy: 'myBudgetValueField desc',
  limit: 3
}).all %}

Alternatively, for just the entry with the highest value:

{% set topFigure = craft.entries({
  section: 'posts',
  relatedTo: { targetElement: myCategory },
  orderBy: 'myBudgetValueField desc'
}).one %}

Of course, this depends on myBudgetValueField being a number or some other easily-sortable value. If you need to format the value, I'd recommend storing it in the unit for comparison, and then visually treating it when you output it (i.e. store 300000, even if you eventually need to output $300,000).


Looking at other issues, there are a few options to handle the GROUP BY issue on MySQL 5.6 > 5.7

Alter the query by using GROUP_CONCAT
Alter the SQL modes

Changing the SQL modes gives you a timeout, but these modes were given in a configuration file. Have you tried it by using an "extra" query?

I.E. session/global:

set session sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

This resets the SQL_MODE to ignore ONLY_FULL_GROUP_BY for every session, in a different way.

Let me know if this changes anything :)


Pixel & Tonic's Contact Form Plugin - POST submissions to Zapier Webhook URL?

By putting the webhook URL in the action field, you're completely bypassing the Contact Form's processing of the POST request and getting back a JSON response from Zapier.

I believe the correct way to do this would be to write your own custom Craft plugin that listens to Contact Form's beforeSend event.

When that event gets fired, you can make an AJAX request (using Guzzle or whatever) to Zapier's URL passing in the required fields, get the response back, do with it what you will, then let the Contact Form's controller finish executing and send them email.


Trying to list entries related to users with a specific category selected

I think I worked this out. It looks like the related entries need to be contained in the user loop. This is what I used to make this work:

{% set categoryUsers = craft.users.relatedTo(category) %}
    {% paginate categoryUsers.limit(1) as entries %}

        {% for categoryUser in entries %}
            {{ categoryUser.username }}

            {% set categoryEntry = craft.entries.section('jobs').authorId(categoryUser.id).first() %}
                {% if categoryEntry %}
                    {{ categoryEntry.positionTitle }} (And other fields not added yet.)
                {% endif %}

Testing the total found: {{ categoryUsers|length }}

        {% endfor %}

    {% if paginate.prevUrl %}&laquo; Previous Page{% endif %}
    {% if paginate.nextUrl %}Next Page &raquo;{% endif %}

    {% endpaginate %}

Still testing, but I think this is the solution. (Unless someone else has a better way of doing this. :))


Password protected area with unique files

It is very easy within your templates to define requirements for whether the page itself, or portions of the content are displayed, and/or route the user to another page if they do not meet the page requirements. For example, you can check whether the user is logged in, belongs to a particular group, is the author of the entry, has a specific permission (and even create your own permissions), and any combination of the above. Here are a few examples, but in general there is a lot flexibility here.

{% if currentUser %}
    ...
{% endif %}

{% if craft.session.isLoggedIn %}
    ...
{% endif %}

{% if currentUser.isInGroup( group ) %}
    ...
{% endif %}

{% if currentUser.id == entry.author.id %}
    ...
{% endif %}

{# custom permission #}
{% if currentUser.can('viewContent') %}
    ...
{% endif %}

When retrieving entries using ElementCriteriaModel you can also find by author, group, relatedTo, etc. so that you can only show the user links to entries that they have access to. To find entries where the author is the currentUser, for example, you could use something like this:

{% set entries = craft.entries.section('blog').authorId(currentUser.id).find() %}
{% for entry in entries %}
    {{ entry.title }}
{% endfor %}

If you wanted to let the site admins assign user(s) to articles on an article-by-article basis independent of author, you could also use an entries fieldtype to create a relationship to user(s), and then find entries using the relatedTo method.

{% set entries = craft.entries.section('blog').relatedTo(currentUser).find() %}
{% for entry in entries %}
    {{ entry.title }}
{% endfor %}

The same  technique can be applied to assets (i.e. pdf files) just as easily.

For more information have a look at the documentation on UserModel, craft.session, craft.users, and ElementCriteriaModel.


Console script tags garbling up non-html output (e.g. json) when in devMode

Just remove these two logging routes from your plugin's init() method in your PluginHandlePlugin.php file:

craft()->log->removeRoute('WebLogRoute');
craft()->log->removeRoute('ProfileLogRoute');

That will prevent the extra logging and profiling information to be output in the browser's console when devMode is enabled.