currentUser global is null. I can't figure out why

Per Brad's request. I am answering my own question.

I figured out that I was logging in via non-www, and accessing the site at www.

So the official answer is to choose either www or non-www. I chose to remove the www from the URL.

Here's my .htaccess for that, including allowing for fonts to be accessed cross domain, as I had issues with this as well.

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Remove www
    RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
    RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

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

<FilesMatch "\.(eot|ttf|otf|woff|svg)">
    Header set Access-Control-Allow-Origin "*"
</FilesMatch>

Note!!! Once this is done, make sure to clear your Craft cache., especially if using fonts/font-icons.


Is it possible to pass a variable to an event in a plugin?

This will not work as the field value will be the new value in both events. You'll need to get the old value from the entry that exists in Craft before saving the new entry, and then perform the comparison.

If the value has changed then store the entry ID to process once the entry has successfully saved.

Note that the $entryIdChanged variable in the anonymous event functions is not in the same as that in the init() method. You can resolve this as follows:

Bring the $entryIdChanged variable into the anonymous functions using the use operator.
PHP will by default "pass by value", meaning that if the value of the variable within the function is changed, it does not get changed outside of the function. So you should pass the variable in "by reference", using an ampersand & before the variable name, which will change it outside the function as well.

See the PHP guide on Passing by Reference.

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

    $entryIdChanged = null;

    // Event: onBeforeSaveEntry
    craft()->on('entries.beforeSaveEntry', function (Event $event) use (&$entryIdChanged)
    {
        $entryModel = $event->params['entry'];
        $newVar     = $entryModel->fieldVar;

        $oldEntry = craft()->entries->getEntryById($entryModel->id);
        $oldVar = $oldEntry !== null ? $oldEntry->fieldVar : '';

        if ($oldVar !== $newVar){
            $entryIdChanged = $entryModel->id;
        }
    });

    // Event: onSaveEntry
    craft()->on('entries.SaveEntry', function (Event $event) use ($entryIdChanged)
    {
        $entryModel = $event->params['entry'];

        if ($entryModel->id === $entryIdChanged){
            // ...
        }
    });
}


MultiAdd - Add a related product by checkbox

From the multiAdd perspective, it only cares that each item you're adding to the cart has some qty - if 0 it will ignore it, if anything positive, it will add that many to the cart, i.e. you only need to see things up such that for each product the minimum info required (for each product that's part of this multiadd process) is:

items[someKey][qty]

items[someKey][purchasableId]

....where of course someKey is the same value for both those inputs.

In terms of how you achieve what you want, that's more of an html form/JS question.  The most obvious approach would be to use some simple JS to listen on the submit event.  If at submit the checkbox is unchecked, you just poke a 0 into the val for that input.  If it is checked, you take the main product's qty valuie and poke that into the input.

To debug this, make sure you check your POST values after the JS is run to check you're submitting what you think you are...in the end what needs to be submitted is super simple as per the above - the only tricky part is the JS to hook it up really.


404 when clicking on the Disqus embed urls

Not sure why they add this param for you; on my own weblog all the suggested links are without ?token. Maybe you previewed that page and had the Disqus embed showing for the preview as well? Best not to include it for previews and older versions.

Anyway, as explained above by default Craft also uses the 'token' param to preview previous versions of the page. That's probably why it's not working now; this token has expired so Craft can't find any version of that page using the requested token anymore and displays a 404 page instead.

The fix is relatively easy: just change the 'tokenParam' config setting to something else:

Craft v2 - https://docs.craftcms.com/v2/config-settings.html#tokenparam

Craft v3 - https://docs.craftcms.com/v3/config/config-settings.html#tokenparam

Then Craft will just ignore it and show the correct page. Just don't forget to also hide the embed for previews otherwise you will get exactly the same problem soon with the new token param.

Edit

Something like this should work to prevent this in the future:

{% if not craft.request.isLivePreview() and not craft.request.getParam( craft.config.get('tokenParam') ) %}
    ... embed code here ..
{% endif %}


requireLogin not redirecting to login page

You should create your /login template with a custom login form. If you do that, the redirect should work as expected:

  craft.session.returnUrl is set to the original URL that included the {% requireLogin %} tag that initiated the redirect to this login form.


Craft can't connect to db.php on live server

The cooldownDuration setting should go in your general.php config file, not in your db.php config file. On your server, is the db on a separate server or is it on the same server? If so, the value for server in example.com should be localhost not server.


Assign a number 1-N for each entry that is returned

If you're in the context of a Twig loop, you have access to the loop variable, which has a number of “magic” properties set.

This allows you to do something like:

{% set posts = craft.entries({ section: 'posts' }).all %}
{% for post in posts %}
  Post #{{ loop.index }} is named: {{ post.title }}<br>
{% endfor %}


setRouteVariables doesn't return errors to the template

I have finished the plugin, with much success, if you wondering you can see it here https://github.com/roundhouse/FormBuilder-Craft-CMS


Getting blocks from matrix and injecting them throughout a page, NOT a single loop statement

I would use a macro to output the contents of a single nugget (matrix block), this way you don't have to repeat the include statement multiple times. The only thing you need to keep track of is the current index, i.e. which item is next. You can't do this inside the macro, since a macro can't have persistent state. You have two options:

Set up a variable to keep track of the current index and increment it every time you include the macro.
Since you have six predefined positions where nuggets may be displayed, you can just hardcode the index and output the item at that index, if it exists.

Macro definition
{% macro nugget(nugget = null) %}
    {% if nugget %}
        {% include '_includes/_components/nugget.twig' with {
            self: {
                size: 'xl',
                bgColor: nugget.circleColour.color[0].class,
                iconPath: nugget.icon[0].path,
                body: nugget.nuggetBody[0].bodyPlain
            }
        } %}
    {% endif %}
{% endmacro %}

{% import _self as macros %}

Having the if-condition inside the macro to handle missing nuggets means you don't have to repeat that if-condition everywhere you want to include a nugget.
Option 1: Index variable
{% set nuggets = entry.nuggets
    .with([
        'nugget:nuggetBody',
        'nugget:icon'
    ])
    .all() %}
{% set nuget_index = 0 %}

{# Nugget position #1 #}
{% include macros.nugget(nuggets[nugget_index] ?? null) %}
{% set nugget_index = nugget_index + 1 %}

{# Nugget position #2 #}
{% include macros.nugget(nuggets[nugget_index] ?? null) %}
{% set nugget_index = nugget_index + 1 %}

{# Nugget position #3 #}
{% include macros.nugget(nuggets[nugget_index] ?? null) %}
{% set nugget_index = nugget_index + 1 %}

Option 2: Hardcoded nugget indexes
{# Nugget position #1 #}
{% include macros.nugget(nuggets[0] ?? null) %}

{# Nugget position #2 #}
{% include macros.nugget(nuggets[1] ?? null) %}

{# Nugget position #3 #}
{% include macros.nugget(nuggets[2] ?? null) %}


In my element type index view, why is the first column always empty?

The first column is reserved for whatever your element model's __toString() function returns. By default that is the element's title, if your element type has editable titles. Otherwise you will need to override that method and return whatever makes sense.


Craft 3 - custom callback after Garnish onDragStop

Garnish’s Base class introduces its own concept of events, that is separate from DOM events.

Here’s how you’d set up the listener:

// get the Craft.MatrixInput object
var matrix = $('.matrix-field').data('matrix');

// attach a handler to its block sorter's sortChange event
matrix.blockSort.on('sortChange', function() {
    // event handler...
});


Getting $craftPath error on server trying to get Craft running

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


Plugin dev with Sendinblue mailer integration

Looks like you're missing the proper namespace.

Should be:

$mailin = new \Sendinblue\Mailin('https://api.sendinblue.com/v2.0', 'dqsdsapicode', 5000);

And here also is the other syntax for a global call in the controller.
Controller beginning would be:

<?php
namespace Craft;

use Sendinblue\Mailin;

class FooController extends BaseController

Then class call will be:

$mailin = new Mailin('https://api.sendinblue.com/v2.0', 'dqsdsapicode', 5000);


There's only one comment syntax for Craft / Twig:

{# ... #}

Anything in between won't be parsed by Twig, so you can comment out multiple lines of Twig and HTML like so:

{#
    {% set var = value %}
    {% for item in seq %}

{{ item }}

    {% endfor %}
#}

As with many other languages you can't nest comments! So if you want to comment out some lines of code that already have comments, you can't do that like so:

{#
    {#
     # Lots of comments going on here
     #}
    {% set var = value %}

    {# I warned you #}
    {% for item in seq %}

{{ item }}

    {% endfor %}
#}

The best workaround I found is to use HTML comments in combination with Twigs verbatim tags (disables Twig parsing).
I added a snippet to my editor for this and use it regularly since:

{% verbatim %}

{% endverbatim %}


So turns out this is to do with the size of the packet being sent to the database cache.

My server had a limit of:
max_allowed_packet = 1M

Doubling this solved my problem.


Display related entries on a category page filtered by another category field

You'd typically use the group filter for this. Depending on what you need to output, be sure to also use eager loading to improve performance.
{% set groupedEntries = craft.entries.with(['yourOutputCatFieldHandle']).relatedTo(category).all()|group('yourOutputCatFieldHandle[0].title') %}

{% for cat, entries in groupedEntries %}

{{ cat }}

        {% for entry in entries %}

{{ entry.title }}

        {% endfor %}

{% endfor %}

EDIT: alternative answer below to allow for using the correct category ordering as per the control panel's Structure order.
Note: this approach requires the supersort plugin.
{# ======================================
First, fetch entries related to this category,
then group the array by each category's
`lft` structure position, then sort the array
by those keys with supersort's ksort function
========================================= #}

{% set groupedEntries = craft.entries.with([
        'yourOutputCatFieldHandle'
    ])
    .relatedTo(category)
    .all()|group('yourOutputCatFieldHandle[0].lft')|supersort('ksort')
%}

{# ======================================
Next, create a hash map of those categories so we can
match up the `lft` left structure position
with the category's title later.
(google "Nested Sets" if you're really bored)
========================================= #}

{% if groupedEntries|length %}
    {% set catTitlesMap = craft.categories.group('yourOutputCatGROUPHandle').all()|group('lft') %}
{% endif %}

{# ======================================
Finally, loop through the grouped array,
matching up the accessory's `lft` position
with the hash map to get the right title...
========================================= #}

{% for cat, entries in groupedEntries %}

{{ catTitlesMap[cat][0].title }}

        {% for entry in entries %}

{{ entry.title }}

        {% endfor %}

{% endfor %}


Only upload the /web folder to the /public_html folder.

All other folders should be one level lower so they're not publicly accessible.

Personally, I'm also wondering why not everything resides in a nice clean /craft folder anymore. Now the craft directories are listed amongst a bunch of other stuff on a lowerlevel directory. It's probably the only one really strange architectural choice. I guess P&T is not using WHM/Cpanel etc.

Anyway: do not upload anything except /web in your public folder.

If you do it like this, the index will work correctly out of the box, since it'll be looking for the /app and all folders one level lower then the /public_html by default.


Assets folder first level open by default

You could modify this JavaScript to do it for you. We currently have it running on a site where this was sought-after

Caveat: Our script opens ALL folders, not just the first level - hence the need to modify.

jQuery(window).on('load', function() {
    var $ = jQuery;

    var openFolders = function() {
        var imageRootLinks = $('a[data-key^="folder:"]');

        $.each(imageRootLinks, function(index, link) {
            var imageRoot = $(link).parent();
            var toggle = imageRoot.find('.toggle');
            if (toggle.length && !imageRoot.hasClass('expanded')) {
                toggle.first().click();
            }
        });
    };

    // open folders in left menu
    openFolders();

    // open folders in image selector
    $(document).ajaxComplete(function(e, status, requestData) {
        if (requestData.url && requestData.url.indexOf('getElements') && requestData.data && requestData.data.indexOf('context=modal&elementType=Asset') != -1) {
            openFolders();
        }
    });
});

Then simply include the JS-file through a plugin

// runs on all requests
public function init() {
    // check that user is logged in and in the control panel
    if ( craft()->request->isCpRequest() && craft()->userSession->isLoggedIn() ) {
        // the includeJsResource method will add a js file to the bottom of the page
        craft()->templates->includeJsResource('myplugin/js/openFolders.js');
    }

}


SEOmatic not merging fields from a related entry

Make sure you're not doing this inside of a {% block %} or you will run into Twig Processing Order / Scoping issues.

There are some good examples of doing that here: Dynamic Twig SEO Meta


How to filter entries by tags array using ['or'] and by category not using or

The relatedTo function accepts multiple different formats. If you want to search for Elements that are related to a list of categories and a list of tags you can do that like this

relatedTo([
    'and',
    ['element' => [1, 2, 3]],
    ['element' => [4, 5, 6]]
]);

This will return you all Elements that are related to the first array and related to the second array. So you goal should be to create an array of category IDs and Tag IDs and pass them together in the relatedTo

To get Elements that are related to all elements of one array and a single one from another array do the following

relatedTo([
    'and',
    ['element' => [1, 2, 3]],
    ['element' => ['and', 4, 5, 6]]
]);


Advanced query/filter based on date and values

You're actually closer than you might think. All you need to do is add your field handles as parameters. I prefer to use the hash style of declaring parameters but either way will work, I just find this easier to read.

{% set params = {
  section : 'events',
  order : 'eventDate asc',
  eventDate : '>=' ~ now,
  eventType : 'green',
  limit : '10'
} %}

{% for event in craft.entries(params) %}
...
{% endfor %}

This method also allows you to easily modify the params hash for whatever reason. For example you might want to set the eventType value to be something else based on the value of a query parameter. To do that you could use the merge tag like so:

{% if craft.request.getParam('eventType') not empty %}

  {% set params = params | merge({
    eventType : craft.request.getParam('eventType')
  }) %}

{% endif %}


Freeform Pro Plugin Mailchimp integration

I had this same issue. We needed to send a contact information form to MailChimp only if the person opted in to receive e-mails. However, the information would always be sent even if the opt-in box was left unchecked. No idea why. I ended up hiding the opt-in box and then added a "yes or no" field that conveyed whether or not the user wanted to receive e-mails. Hope that help and makes sense!


Is it possible to cache variables using the {% cache %} tag?

You can accomplish this by using the set/endset tags to create a variable from the cached output:

{% set finalVariable %}
    {% cache %}
        {# heavy lifting (like queries) here #}
        {# output the contents of your variable here #}
        your output here or {{ yourOutputHere }}
    {% endcache %}
{% endset %}

In the above example the finalVariable will be set to the value of the cached content.

Or, in the case of the code example used in the question, something like this could be used:

{% set id %}{% spaceless %}
    {% cache using key "cacheId" %}
        1
    {% endcache %}
{% endspaceless %}{% endset %}

It's a very basic example that would probably never be used, but the id variable would be set to a string of 1 from the cacheId cache.

Note: The spaceless tags are just used to remove the whitespace.


How do I prevent Redactor from wrapping  with

I’m not sure that this is possible – Redactor has some checks in its code to make sure everything lives within a block-level element like <p>.

You might be better off using a Matrix field instead, with Text and Image block types. You can still use a Redactor field within your Text block type; just disable the Image toolbar button on it from your Redactor config in craft/config/redactor/. Give the Image block type an actual Assets field.

Then from your templates you’ll have full control over the image markup.

{% for block in entry.myMatrixField %}

    {% if block.type == 'text' %}

        {{ block.myRichTextField }}

    {% elseif block.type == 'image' %}

        {% set image = block.myAssetsField.first() %}
        {% if image %}
            <img src="{{ image.url }}" width="{{ image.width }}" height="{{ image.height }}" alt="{{ image.title }}">
        {% endif %}

    {% endif %}

{% endfor %}


How do entry elements render a default string but also return an object at the same time?

It's the __toString() magic method:

The __toString() method allows a class to decide how it will react
when it is treated like a string.

https://www.php.net/manual/en/language.oop5.magic.php#object.tostring


Unexpected token "punctuation" of value "?"

The issue was a plugin’s composer.json that was loading an older version of Twig as a nested dependancy, which was overriding Craft’s Twig.

Running a composer update for that plugin rectified the issue.


The function is

public function getSetByHandle(string $globalSetHandle, int $siteId = null)

Thus you can grab all the siteIds you want and loop through them

{% for siteId in sites %}
    {% set setForSiteId = craft.app.getGlobals().getSetByHandle('handle', siteId) %}
{% endfor %}


Viewing Assets (PDFs) associated with an entry directly from that entry screen

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


Fixed by doing the following commands:

chown -R www-data:www-data /var/www
service apache2 restart


How to darken an image using the Imager plugin

Seems like you might be better using colorBlend?

{% set image = block.image.first() %}
{% set transformedImage = craft.imager.transformImage(image, {
  width: 1500,
  height: 700,
  effects: {
    colorBlend: ['rgb(0, 0, 0)', 0.4] }
  }
}) %}


Craft CMS 3 Boilerpoint Web Project Setups Available?

A good starting point would be the nystudio107 or marbles craft scaffolding projects:

https://github.com/nystudio107/craft

https://github.com/Marbles/craft


How can I server Craft transform assets statically (not through Craft/PHP)

This happens automatically if you use asset.getUrl(transform)...


How can I troubleshoot why my queue of tasks in stuck in Craft 3?

I typically just truncate (delete all of the rows) the queue table if something goes wrong with a task.

Then I delete all of the files in storage/logs/ and I try to reproduce the problem. If it still happens, then I look in queue.log and web.log to see what the issue is.

Usually searching on [error] finds what I'm looking for pretty easily. Occasionally I have to browse through the file to find the actual problem, but that's why I delete the log files before I do it, so there isn't as much to wade through.

Relevant articles I wrote since this answer:

Robust queue job handling in Craft CMS
Zen and the Art of Craft CMS Log File Reading


To delete an Section, go to Settings -> Sections, then click the fain't, almost invisible icon to the right of the offending Section name.


Image transformation of tif image does not work

I found the way to create thumbnails of tif files. You have to change the function isImageManipulatable in the file /craft/app/helpers/ImageHelper.php:

public static function isImageManipulatable($extension)
{
    $extensions = array('jpg', 'jpeg', 'gif', 'png', 'wbmp', 'xbm');

   if (craft()->images->isImagick())
    {
        $extensions[] = 'svg';
    }

    return in_array(mb_strtolower($extension), $extensions);

}

To this:

public static function isImageManipulatable($extension)
{
    $extensions = array('jpg', 'jpeg', 'gif', 'png', 'wbmp', 'xbm');

   if (craft()->images->isImagick())
    {
        $extensions[] = 'svg';
        $extensions[] = 'tif';
    }

    return in_array(mb_strtolower($extension), $extensions);

}

I know, changing core code is not a real solution: i posted this change as a Craft feature request -> http://feedback.buildwithcraft.com/forums/285221-feature-requests/suggestions/8794456-better-support-of-image-types-in-image-transformat


table field - make one culumn translatable, other common for all languages

If there’s a predetermined set of feature names, then you could translate them using static message translations.

{% for row in entry.myTableField %}

{{ row.featureName|t }}

{{ row.featureValue }}

{% endfor %}

If new products will always be introducing new feature names, then that might become impractical, as you’d be constantsly adding new values to your translation file.

You could set up a custom translation message source + category in config/app.php that pulls translations in from a separate, translatable Table field on a Global Set, for instance, but that could be overkill.

The other option is to use Verbb’s Super Table plugin, which will let you mark certain fields as translatable.


File upload error in MS Azure after custom domain was pointed to Azure server

MS support team helped to resolve the issue. I will post the steps to be followed.

In your CMS Admin, Under Assets source ->
File system path: images/
URL: http://example.azurewebsites.net/images
(Here the images directory is under public directory)
In Azure portal, Add the following App settings in Application setting of your App service:
key: WEBSITE_DYNAMIC_CACHE
value: 0
Restart the Azure App service.


links to another website without my own url

I assume that subHeading is a plain text field.
Just a guess, are you inserting a string that can be interpreted as a relative path on your website?

Ex. google.com vs https://www.google.com

The first will lead to yoursite.com/google.com, the latter should work fine.


.type("not landing") won't work. If you reread the post you linked it also states this — I believe it was more of a feature request. You will need to test each entry and either use it directly or merge it into an array for later use.

{% set entries = craft.entries.section("pages") %}
{% for entry in entries if entry.type != "landing" %}
    {{ entry.title }}
{% endfor %}

or

{% set filteredEntries = [] %}
{% set entries = craft.entries.section("pages") %}
{% for entry in entries if entry.type != "landing" %}
    {% set filteredEntries = filteredEntries|merge(entry) %}
{% endfor %}

As a side note, if you are using a structure with a hierarchy where landing pages are at the root level and all other entries are children, then you can also use:

{% set entries = craft.entries.section("pages").level('> 1') %}


Unable to store Model in Commerce Order Fields

When you assign element IDs to a relation field you need to pass the data in an array format.

See this related answer: In a plugin, how do I save an entry with a related entry

Key information in that answer:

<input type="text" name="fields[customTextField]" value="My Text Data">
<input type="text" name="fields[customRelationField][]" value="101">

Note that in the input field name of 'customRelationField' relations field we are passing an array: fields[customRelationField][].

Also note the relation field data is a full replace. So if you ever want to add an element ID to an existing relation field that has relation already set, you need to get the existing IDs as an array and add your additional IDs when updating the field.


You'd need to get the tag model first.

{% set tag = craft.tags.search('My Tag').first() %}
{% if tag %}
    {% set entries = craft.entries.relatedTo(tag) %}
{% endif %}

Replace search with whatever other information you have from the tag, to get more precise results, e.g., slug, id properties.


How to Check All Users against UserGroup

Got it all sorted:

{% if craft.users.group('myusergroup').total() > 0 %}


Asset Field: Select a folder instead of all images

You can create a new field with these functions. Note: this is a very basic example, you would usually want to do this with a template but I don't have much time

class FolderAssetField extends Field {
    // Static Methods
    // =========================================================================

    public $folderId;

    /**
     * Returns the display name of this class.
     *
     * @return string The display name of this class.
     */
    public static function displayName(): string{
        return 'Folder';
    }

    /**
     * @param $value
     * @param ElementInterface|null $element
     * @return string
     */
    public function getInputHtml($value, ElementInterface $element = null): string
    {
        $allFileModels = \craft\records\VolumeFolder::find()->all();
        $string = 'select a folder
<select name="' . $this->handle .  '">';
        /** @var VolumeFolder $folder */
        foreach ($allFileModels as $folder){
            $selected = ((int)$value === $folder->id)? 'selected="selected' : '';
            $string .= '<option ' . $selected .  ' value="' . $folder->id . '">' . $folder->name .  '</option>';
        }
        $string .= '</select>';

        return $string;
    }

}

Your field will then contain the folderId of the selected folder. You can then  get all assets for this folder with

/** @var AssetQuery $assetQuery */
$assetQuery = \craft\elements\Asset::find();
$assets = $assetQuery->folderId($value)->all();

or in Twig

{% set assets = craft.assets.folderId(entry.fieldHanlde).all() %}
{% for file in assets %}
    {{ file.title }}

{% endfor %}

You could also use the normalizeValue function to prepare this Query. The Redactor plugin has some good examples here


Using Amazon S3 with Craft 2.x in Frankfurt region

The AWS Frankfurt region (eu-central-1) does only support the "new" v4 signature. Craft 2 uses the v2 signature of the S3 API and that's not easy to fix.

Ireland (eu-west-1) should be good enough in terms of latency.


How to link to controller actions in a Craft 3 plugin?

Apparently I figured it out. Would still like a better way of doing this, but here's the solution I found to be working:

In your Plugin class, you have to add a public $controllerMap array. For my example plugin above, here's what I would have to add to that $controllerMap array:

use Very\Waffle\Controllers\SyrupController;

class Plugin extends \craft\base\Plugin
{

    /** @var array */
    public $controllerMap = [
        'syrup' => SyrupController::class,
    ];

    // other code here, obviously
}


Depends on whether the user field is on the product or a variant.

If the custom field is on the product:

{% set products = craft.commerce.products.relatedTo({
    sourceElement: currentUser,
    field: 'userFieldName'
}) %}

If the custom field is on the variant:

{% set variantCriteria = craft.commerce.variants.relatedTo({
    sourceElement: currentUser,
    field: 'userFieldName'
}) %}

{% set products = craft.commerce.products.hasVariant(variantCriteria) %}


How can I order each product variant in my templates?

product.variants just returns an actual array of the variants, not an ElementCriteriaModel. So you can’t chain on additional params like order.

To get variants using custom parameters, you can do this:

{% set variants = craft.commerce.variants({
    product: product,
    order: 'price asc'
}) %}

{% for purchasable in variants %}
    // ...
{% endfor %}


Craft 3 FeedMe - Help accessing deeper XML nodes

I think your problem is that <listitem xml:id="A50-3487-2"> has an attribute, so you would need to use <p>{{ node.itemizedlist.listitem['@'].para }}</p> to get the node value.

See the bottom of the docs here:
https://docs.craftcms.com/feed-me/v4/feature-tour/using-in-your-templates.html


Possible have matrix rows collapsed by default in the Control Panel?

Inject this piece of JS in your CP and they will always be closed by default:

$('.matrixblock').each(function() {
    $(this).addClass('collapsed');
    Craft.MatrixInput.rememberCollapsedBlockId($(this).data('id'));
});

Here's an example plugin that will inject it in the CP: https://gist.github.com/boboldehampsink/6bb9e5296977a99c39b1


Express Server posting user data to Craft

You'd normally use a front-end form to create users on a Craft site. You can add fields to this form to submit more than the standard set of fields. I believe you could use the same form within your Express app. You are just sending the data via a POST request.

Check the documentation for an example.


Using multiple elementTypes in Element API

The results query could not be the same, you have to separate them.
use craft\commerce\elements\Product;
use craft\elements\Entry;

return [
    'endpoints' => [
        'search/product.json' => function () {
            // settings
            $phrase   = Craft::$app->request->getParam('query');
            $criteria = [
                'search' => 'title:' . $phrase,
            ];

            return [
                'elementType' => Product::class,
                'criteria'    => $criteria,
                'paginate'    => false,
                'transformer' => function (Product $product) {
                    return [
                        'title' => $product->title,
                        'url'   => $product->url,
                    ];
                },
            ];
        },
        'search/news.json' => function () {
            // settings
            $phrase   = Craft::$app->request->getParam('query');
            $criteria = [
                'search' => 'title:' . $phrase,
            ];

            return [
                'elementType' => Entry::class,
                'criteria'    => $criteria,
                'paginate'    => false,
                'transformer' => function (Entry $entry) {
                    return [
                        'title' => $entry->title,
                        'url'   => $entry->url,
                    ];
                },
            ];
        },
    ]
];

UPDATED: 18/12/2020
Anyway, I've found a new way that allows you o use the multiple entries in an endpoint.
<?php

use craft\commerce\elements\Product;
use craft\elements\Entry;

return [
    'endpoints' => [
        'search.json' => function () {
            // settings
            $phrase         = \Craft::$app->request->getParam('query');
            $articles       = Entry::find()->search($phrase)->limit(10)->all();
            $articleObjects = [];

            if ($articles) {
                $articleTemplateName = ''; // your article template path
                foreach ($articles as $article) {
                    $articleObjects[] = \Craft::$app->getView()->renderTemplate($articleTemplateName, ['post' => $article]);
                }
            }

            return [
                'elementType' => Product::class,
                'criteria'    => [
                    'search' => 'title:' . $phrase,
                ],
                'paginate'    => false,
                'transformer' => function (Product $product) {
                    return [
                        'title' => $product->title,
                        'url'   => $product->url,
                    ];
                },
                'meta'        => [
                    'news' => $articleObjects
                ]
            ];
        },
    ]
];


Let admin create price offers/quotes for customers in Commerce

I would advise raising this as a feature request on Github (i.e. issue).

https://github.com/craftcms/commerce/issues

Commerce 3 has back end order entry (i.e. admins can enter orders on behalf of customers), but extending this to quotes etc. would be super useful and that would be  a good place to get the conversation happening.


How to access HTML input values from Twig and vice versa

You can do it without JavaScript (if you don't mind the page refreshing) by accessing the request variable:

https://docs.craftcms.com/api/v3/craft-web-twig-variables-request.html#public-methods

{{ craft.app.request.getParam('foo') }} {# Should be the value of the input named 'foo' #}


Just because EmailService::sendEmailByKey() requires you to pass in a UserModel, doesn’t mean that the model has to represent an actual saved user. You can create one on the spot for them:

$user = new UserModel();
$user->email = 'sergster@abc.xyz';
$user->firstName = 'John'; // optional
$user->lastName = 'Doe'; // optional

craft()->email->sendEmailByKey($user, 'my_key', $variables);


If I understand your question and structure correctly, then this might work.

{% entries = craft.entries.section('series').limit(null) %}
{% mostRecentSermons = [] %}

{% for entry in entries %}

    {# retrieve most recent sermon related to series #}
    {% set sermon = craft.entries.section('sermons').relatedTo(entry).order('postDate desc').first %}

    {# merge sermon into mostRecentSermons array #}
    {% set mostRecentSermons = mostRecentSermons|merge([sermon]) %}

{% endfor %}

If you need to worry about duplicates then you can use {% if not sermon in mostRecentSermons %} before merging.

You may also want to wrap this in {% cache %}{% endcache %} tags to improve performance.


Check if a table field’s column has a value

You were close...

Chaning this:

{% if row.url == 0 %}

to this:

{% if row.url|length %}

should do it for you.


Switch to graphical buttons in Redactor 2

You could use my plugin Redactor Icon Buttons.

It includes the icons from the (old) Redactor 10 editor and you can map icons to buttons via a iconMapping config setting. It also allows to use a custom icon set.

If you still want to write your own plugin, have a look at the source code of P&T’s Redactor Clips plugin.


Making a dynamic {{ siteUrl }} for local mobile testing

Hey Jeremy you can actually make siteUrl work using Multi-Enviroment Configs and your general.php file will end up looking something like this.

return array(
'*' => array(
    // ...
),

'example.dev' => array(
    // ...

    'environmentVariables' => array(
        'basePath' => '/users/brandon/Sites/example.dev/public/',
        'baseUrl'  => 'http://example.dev/',
    )
),

'example.com' => array(
    // ...

    'environmentVariables' => array(
        'basePath' => '/storage/av12345/www/public_html/',
        'baseUrl'  => 'http://example.com/',
    )
)

);


You can't automatically expand variables inside strings in Twig as you would normally do in PHP.

Instead, you have to concatenate your strings.

{% set seo = craft.seo.custom('Discount codes and vouchers for ' ~ query, 'You searched for ' ~ query ~ '. Check out the latest live ' ~ query ~ ' discount codes & voucher codes for ' ~ now|date('m') ~ ' ' ~ now|date('Y') ~ ' only at Vouchertoday.uk') %}


How to truncate auto-generated entry titles?

You can use any Twig in the dynamic title field. There are plugins that provide Twig filters to truncate text, but here’s how you can do simple truncation without any plugin.

{{ object.myTextField|length > 50 ? object.myTextField|slice(0, 50) ~ '...' : object.myTextField }}


How to make an HTTP request from a plugin?

Craft uses an HTTP library called Guzzle, and it's built-in so you can import and use it from within your plugin. Here's an example:

// imports
use GuzzleHttp;

// GET request

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://example.com', [
  'query' => ['exampleParam' => 'example']
]);
$responseBody = json_decode($response->getBody(), true);

// POST request
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://example.com/api', [
  'form_params' => [
    'example' => 'example',
  ]
]);
$responseBody = json_decode($response->getBody(), true);

To figure out how to properly format your Guzzle request, refer to the Guzzle Docs.


I updated phpMyAdmin to the latest stable version and it worked!


Filter Entries within a page dynamically based on category

You will need to use some JavaScript, since all twig code is parsed on the server and sent to the browser as HTML.


I came up with a less than ideal workout, but it's still somewhat of a solution

I first created a channel to contain all of the "child" entry types. This allowed each one to have a matrix property to account for the dynamic creation of the "child" fields

I then created another channel with an entry type that also contains an Entry select field which allows for unlimited selection of Entries of the "child" types


{{ entry.image.first().url }} won't show image

By the way, is your Craft CMS version 3.x? If so, using "one" is recommended instead of "first", which is deprecated.


Including CSS/JS assets from template folder

Your example code worked for me - This may be down to using MAMP and having a config file that handles my siteUrl and assetsUrl.

There are a few questions already on Stack Exchange that relate to your folder structure and how to include assets in different templates.


You'd do it from another plugin, just as if you were latching onto any of Craft's native hooks.

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

You can use the businessLogic plugin as a starting point or use https://pluginfactory.io to generate boilerplate plugin code.


Craft always saves a complete DateTime value to the database, even if you only make it set / show the time part of it in the Control Panel.

To ignore the date part (which in this case is set to the day you saved your entry) within the order parameter, you can make use of the time() MySQL function:

{% set entries = craft.entries.section('events').order('eventDate', 'time(eventStart)') %}


Change/update the default user profile photo/thumbnail folder location

In Craft 3 the place that users photos get stored in are proper Asset Volumes, meaning they can be stored in a folder on the local file system, or on S3, Google Cloud, or any other place that a plugin provides a Volume for.

Once you create a Volume for user photos, go to Settings->Users->Settings in the Control Panel and you can choose that Volume under the "User Photo Volume" settings.


What will happen if we change the field type in the fields (settings -> fields) in Craft 3?

It depends on the field type. Many of them you can change without problems, while others would make no sense. If you are, for instance, changing a text field to an image field, Craft obviously wouldn't know what to do with it. But if you change an Email field to a Plain Text field, it would keep the value.

The dropdown will have a warning icon when it's unsafe to change the field type. Sometimes it may work, even though the results are unpredictable. For instance, if you change a Plain Text field to a Multi-Select field, the text will be the value of the field (I think), but there is no guarantee that it is a valid option for the Multi-Select.

Also, the other way, changing a Number field to a Plain Text field causes no problems. If you change a Plain Text to a Number field, you have no guarantee that the text actually represents a number. But I think it will keep the value, but that you will get a validation error on trying to save it the next time, if the value is not valid.


Going from a static site generator (Jekyll or Hugo) to Craft CMS; Export/migrations options?

There is a good plugin called FeedMe that can help with imports. We used it migrating a pretty large EE site without issue. If you can spit out a XML, RSS, ATOM or JSON feed, it should be able to import it.

FeedMe Plugin

I am not sure if it is Craft 3 ready yet, though.


You could take a look at the Element API to help bridge the gap between your React front-end and your Craft back-end. That will at least help you with getting data out of Craft.

As far as creating new pages and modules you'd use Craft's Control Panel (CP). You're going to have to take a look at the Craft Documentation in particular Sections & Entries.


Matrix with an entries field and need to grab category title

To achieve structure:

Country Name A

Reseller C

Country Name C

Reseller B
Reseller D

With configuration:

Category Countries

Channel Resellers:

rdCountry (Country Categories) field

Channel Products:

chooseResellers (Matrix) field

block

chooseReseller (Reseller Entries) field

You gonna need code like this:

{% for entry in craft.entries.slug(entrySlug).find() %}
    {% set countries = {} %}
    {% for block in entry.chooseResellers %}
        {% for reseller in block.chooseReseller.with(['rdCountry']) %}
            {% set countryName = reseller.rdCountry[0].title %}

            {% if countries[countryName] is defined %}
                {% set temp = countries[countryName] | merge([reseller]) %}
                {% set countries = countries | merge({(countryName): temp}) %}
            {% else %}
                {% set countries = countries | merge({(countryName): [reseller]}) %}
            {% endif %}

        {% endfor %}
    {% endfor %}

    {% for countryName, resellers in countries %}

{{ countryName }}

        {% for reseller in resellers %}

{{ reseller.title }}

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

Because of the current section/field/relation configuration we need to use countries temporary array to store Country => Reseller structure.

.with(['rdCountry']) is what you call eager loading. It allows you to reduce sql queries, speed up the whole process. With eager loaded entries field you replace find() with index number.

countries looks like this at the end:

{
   "Country Name A":[
      {
         "title":"Reseller C"
      }
   ],
   "Country Name C":[
      {
         "title":"Reseller B"
      },
      {
         "title":"Reseller D"
      }
   ]
}


Pagination with randomly ordered entries

Why is this happening?

  Why am I seeing duplicates?

When the database is told to sort by random, the entire list of entries is being sorted into a random order before your required page of items is being sliced out of it. This random sort is fresh and different every time the query is made, so when you ask for page 2, it's starting from a different random order, then slicing out items 10 through 18.

  Oddly it doesn't feel like there is enough duplication to make me think my method is wrong. From about 100 entries, showing 9 at a time I might see 1 or 2 duplicates at most.

I don't know how to calculate the exact probability, but I ran a little simulation, and assuming you mean you have 100 entries total and are looking for duplicates in two pages of nine entries each, you'd expect about 1 duplicate.

Solution

A solution is to pass in a seed value to RAND() so that it will use the same random order for each query. I've put '123' below, but I'm using the current day in my project so the order changes each day. You could also choose a randomized seed per user and remember it via a cookie or similar.

{% paginate craft.entries({
        section: 'customers',
        limit: 9,
        orderBy: 'RAND(123)',
    })
    as pageInfo, pageEntries
%}


I finally found what the problem was.

The translations files (/craft/translations/de.php) were encoded as "UTF-8 with BOM"
I opened these files in Sublime text and saved them as regular old UTF-8, which fixed the issue.


I solved this by overriding the routes set by craft commerce and extend the OrderController and the Order element.

This is not a good solution (I'm going upload this as a plugin) and if several plugins overwrite the same route, only the latest plugin will work.

If anyone have a proper solution I'll accept that. I'll leave this answer here in the meantime.

Plugin::init()

    Event::on(UrlManager::class, UrlManager::EVENT_REGISTER_CP_URL_RULES, function (RegisterUrlRulesEvent $event) {
        $event->rules['commerce/orders'] = 'commerce-easy-order-management/orders/order-index';
        $event->rules['commerce/orders/<orderId:\d+>'] = 'commerce-easy-order-management/orders/edit-order';
        $event->rules['commerce/orders/action/<orderId:\d+>'] = 'commerce-easy-order-management/orders/order-action';
    });

controllers\OrdersController

class OrdersController extends \craft\commerce\controllers\OrdersController
{
    /**
     * Index of Orders
     * Overwriting commerce/controllers/OrderController::actionOrderIndex()
     *
     * @return Response
     * @throws \Throwable
     */
    public function actionOrderIndex(): Response
    {
        // Remove all incomplete carts older than a certain date in config.
        Plugin::getInstance()->getCarts()->purgeIncompleteCarts();

        Craft::$app->view->registerCssFile('https://use.fontawesome.com/releases/v5.3.1/css/all.css');

        return $this->renderTemplate('commerce-easy-order-management/orders/_index');
    }
}

elements\Order

class Order extends \craft\commerce\elements\Order
{
    /**
     * @inheritdoc
     */
    public function getTableAttributeHtml(string $attribute): string
    {
        if($attribute !== 'orderActions') return parent::getTableAttributeHtml($attribute);
        return 'MyActionHTML';
    }

    /**
     * @inheritdoc
     */
    protected static function defineTableAttributes(): array
    {
        $attributes = parent::defineTableAttributes();
        $attributes['orderActions'] = ['label' => Craft::t('commerce', 'Actions')];
        return $attributes;
    }
}

templates/orders/_index.html

{% extends "_layouts/elementindex" %}

{% set title = "Orders"|t('commerce') %}
{% set docTitle = title~' - '~'Commerce' %}
{% set elementType = 'MY_NAMESPACE\\elements\\Order' %}
{% set selectedTab = 'orders' %}
{% set selectedSubnavItem = "orders" %}
{% set bodyClass = (bodyClass is defined ? bodyClass~' ' : '') ~ "commerceorders     commerceordersindex" %}

{% do craft.app.view.registerTranslations('commerce', [
    "Total Revenue",
    "Last 7 days",
    "Last 30 days",
    "Last Week",
    "Last Month",
    "Custom Range",
    "Apply"
]) %}


How can I get the server's timezone in a Craft plugin?

Use ini_get('date.timezone').

Source: http://php.net/manual/en/function.ini-get.php


CRAFT_BASE_PATH problems when installing Craft 3 in subdirectory

If I understand correctly, take the content of web and place it in subdir so you have:

html/
├── subdir/
│   └── craft/ (config, vendor, templates, .env etc)
│   └── cpresources
│   └── .htaccess
│   └── index.php
└── the main site

Then in index.php do :

define('CRAFT_BASE_PATH', dirname(__DIR__) . '/subdir/craft');

And you should have your craft site accessible at mainsite.com/subdir


Yes, with the launch of Craft 3, Pixel and Tonic have provided some documentation on switching from Craft 2 syntax to Craft 3.


Why is htaccess file not named ".htaccess" on fresh install?

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

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


How to allow guest to make entry without login

The Guest Entries plugin is made for this scenario!


Craft 3 - How do you programatically update a field type that is a Category?

You should insert an array of ids - not an array of elements - in order to make it work. That's basically it

$new_$nearby_locations[] = $nearby_location->id;

(that's usually better than array push too)

Edit

But your error message sounds more like your slug is an Array or something like this. Do you change any other fields somewhere?


I believe this is caused by not including array in the function parameter, preceding the variable.

Changing to public function actionEdit (array $variables = [ ]) should do the trick.

As a bonus - can anyone explain why? Seems like the $variables variable needs to be cast as an array?


I recommend the tutorial https://craftquest.io/courses/how-to-create-craft-plugin Now, It is free after registration. After 1/2h you have your own plugin with settings and form with controller. Simple, straightforward, with craft form component. Your code is quite messy, try tutorial.


Allow a User Group to access plugin pages (without hasCpSection)

Register new user permissions to restrict access to those pages using the registerUserPermissions hook.
Then use registerCpRoutes to setup routes to a controller action which checks for required user permissions before rendering the templates.

Sorry if I’m missing something, but I don’t see how this has anything to do with the hasCpSection function.


They both use the same underlying library, so things like this should be identical in both of them. But there was a recent GH issue that might answer this for you: https://github.com/nystudio107/craft-typogrify/issues/33


Filter out part of _layout on a specific template

Sorry... while searching for an answer to something else I discovered the solution to this :/

{% if craft.request.getSegment(1) != index.uri %}

    .... leave this chunk of code out

{% endif %}


What does the CategorySources plugin do?

IMO, the plugin serves two purposes... one of which is simply to serve as an example for how to use the modifyEntrySources hook.

Beyond that, the plugin will provide you with an alternative way to view your Entries. You'll notice that the categories which you selected now appear as entry sources on the left sidebar under the Entries tab.

Oh, and Craft 2.3.2629 is required... that's when modifyEntrySources was introduced.


Retrieve Asset Filename from an entry, inside a matrix field

I would first check if you actually set up the Field handles you are currently using in your template:

Matrix Field handle: 'contentPrimary'
Block Type handle: 'widget'
Entries Field handle: 'widgetPrimary'
Assets Field handle: 'widgets'

Then try to use the first() method instead of direct access to the array.
Or use direct access only after adding find() method that creates an array out of your ElementCriteriaModel. Edit: Direct access like this: myArray[0] should also work with an ElementCriteriaModel, but throws errors if no first elements exists (→ read Brandon's answer on this topic for more info).

{% for block in entry.contentPrimary %}
    {% switch block.type %}
        {% case "widget" %}
            {% set relatedEntry = block.widgetPrimary.first() %}
            {% if relatedEntry %}
                {% set asset = relatedEntry.widgets.first() %}
                {% if asset %}
                    {{ asset.title }}
                {% endif %}
            {% endif %}
    {% endswitch %}
{% endfor %}


Template query: Advanced section query to get unique items from custom entry type field

Try this:

// Return all ids for your posts' section
{% set postIds = craft.entries.section('blogEntries').ids() %}

// Look for and return employees which have a relation with any of the posts returned in 'postIds'
{% set writers = craft.entries.section('employee').relatedTo({ sourceElement: entryIds }).all() %}

// Loop and display
{% for writer in writers %}
    {{ writer.title }} <br>
{% endfor %}

This will only return a list of writers who have written a post, not a list of all writers but I guess that's what you want..?


I'm not sure if this helps, but here is how I (attempt) to manage deployments/installs.

I first create a user so I'm not using the root account. I tie that user to the apache user group. We'll call him 'user1'.

I use beanstalk to deploy, and the deployment credentials are for 'user1'.

Once all of the files have deployed for the first time, I'll log into the server via terminal, and chown the project directory: chown -R user1:apache

Next, I'll make sure everything has the correct permissions: chmod -R 754 mysite.com

Next, I know that Craft needs to be able to write to:

/craft/app
/craft/config
/craft/storage

I will chmod those directories to 774. chmod -R 774. Since 'user1' belongs to apache, it can read/write to the appropriate directories.

Hope this helps!


How can I specify what happens when someone calls my fieldtype without any further dot chains?

entry.myFieldHandle will return whatever the field type’s prepValue() function returns.

If you always want that to be HTML, then prepValue() can just return the HTML as a string or \Twig_Markup object via TemplateHelper::getRaw() so devs don't have to type |raw when outputting the value.

If you want it to be an object that supports sub-properties and methods, then have prepValue() return the object. Give the class a __toString() method, which defines the string that should be returned when the object is treated like a string. Behind the scenes, __toString() is what will be called when a template has {{ entry.myFieldHandle }}. But note that this is a PHP construct and PHP mandates that the method returns an actual string, so you can’t return a \Twig_Markup object here. Devs will have to type {{ entry.myFieldHandle|raw }} to prevent Twig from escaping the HTML.


Rebuilding my portfolio site from scratch in CraftCMS 3 and having an issue getting content to display

Craft 3.5 (not sure when this occurred so maybe earlier) seems to default to a "save" draft"c option for new entries. You have to publish the draft before it can go live. All working now though.


If you don't mind using the search parameter you could add it like this:

{% set beer = 'a' %}
{% set allCats = craft.categories.search('title:' ~ beer ~ '*').limit(null) %}


You can get any validations errors on the category after you've attempted to save it with CategoryModel::getAllErrors() or \CModel::getErrors().

You're also setting the groupId on the Category's ContentModel, but this property is actually on the Category record itself as it sets the relationship directly.

$category = new CategoryModel();
$category->groupId = $this->category_group_id;

$category->SetContentFromPost(array(
    'title' => $data[0],
    'colorCode' => $data[1],
    'colorPreview' => $data[2],
));

if (craft()->categories->saveCategory($category))
{
    return true;
}
else
{
    // dump the error messages
    Craft::dd($category->getAllErrors());
}


conditional does not run first in a file that is included using the extends feature for twig

The issue here is that extends isn't the same thing, neither conceptually or technically, as an include. When you extend a template with a layout template, the template is "decorated" by the layout. So, what's happening is that the code in the layout is parsed after all of the code in the template.

Check out this article on straightupcraft explains the order of which things happen in Twig. In short:

1) All code in your template, except code inside blocks, gets processed.

2) All code in your layout, except code inside blocks, gets processed.

3) Code inside blocks gets processed.

So, what the solution to your problem is, depends on your setup. But, if your code that accesses currentUser is inside the block in your page template, the redirect should fire first. If you need to access currentUser outside of the blocks in your page template, you have to do the redirect there.


How to retrieve Site Url and Site Name in Plugin

In Craft 3 you can do this:
use craft\helpers\UrlHelper;
UrlHelper::siteUrl();

Craft::$app->sites->currentSite->name;


Entry field not outputting after {% set... %} code in template

Here's your problem... You're redefining entry halfway down the page.

This page clearly uses the section's built-in routing functionality. I can tell because you use entry.body near the top of your page without explicitly declaring the value of entry.

However, you later on use {% set entry %} to reassign the value of entry. Based on the new value of entry, the entry.footer property no longer exists or is empty.

How to fix it...

Instead of {% set entry %}, use a different variable name:

{% set getQuoteEntry = craft.entries.slug('get-a-quote').first %}
request a quote

This will leave the original value of entry untouched, and you'll still have access to entry.footer at the bottom of the page.


Noob here. Can I buy a license without installing the software?

It's not possible to do this by yourself... reach out to Pixel & Tonic directly:

  support@craftcms.com

If this software already is installed somewhere public, you can simply log in and pay for it directly.


How to make calls to render a fixed asset

This is more of a suggestion than a real answer (assuming the folderId and filename are correct, what you've got should probably work), but anyway:

I'd strongly advise against hard coding an Asset into a template like this. By creating a Global set with an Assets field, you'll save yourself a lot of (potential) trouble, both short and long term.

Here's how your code could look using a Global set called siteSettings, with an Assets field called noMorePostsImage:

{% set asset = siteSettings.noMorePostsImage.first() %}
{% set thumb = {
    mode: 'crop',
    width: 800,
    height: 600,
    quality: 75,
    position: 'center-center'
} %}
{% if asset %}
    <img alt="No More Posts" class="img-responsive center-block" src="{{ asset.getUrl(thumb) }}" />
{% endif %}

So, the code is (a little bit) simpler than what you currently have, and (more importantly) the chance of something going wrong is much smaller. As a bonus, it'll be much simpler to change the image later on, should the need arise. You'll also avoid future issues if someone e.g. moves or renames the Asset from inside Craft.

If your content editor(s) shouldn't be able to change or remove the image, you can simply exclude the Global set from your content editors' user group permissions (assuming you're not running Craft Personal, of course).


How can I query for entries that have one of two Lightswitch fields enabled?

Craft 3

Thanks to the where() function this has become easy in Craft 3.

{% set query = craft.entries.where([
    'or',
    {'field_lightswitchA': 1},
    {'field_lightswitchB': 1},
]) %}

Craft 2

Custom field parameters are being added with and-logic, so you'd indeed have to
do it from PHP with custom dbCommands.

You could either approach it with converting a criteria model to a dbCommand object using the buildElementsQuery method, or you listen for elements.buildElementsQuery events and modify the dbCommand if the criteria model meets certain conditions.

craft()->on('elements.buildElementsQuery', function(Event $event) {
    $criteria = $event->params['criteria'];
    $dbCommand = $event->params['query'];

    if (isset($criteria->or_lightswitchA) && isset($criteria->or_lightswitchB)) {
        $params = array(
            ':lightswitchA_value' => $criteria->or_lightswitchA,
            ':lightswitchB_value' => $criteria->or_lightswitchB,
        );

        $conditions = array('or',
            'content.field_lightswitchA=:lightswitchA_value',
            'content.field_lightswitchB=:lightswitchB_value',
        );

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

Here's how you'd trigger that listener from your criteria model in Twig.

{% set entries = craft.entries({
    or_lightswitchA: 1,
    or_lightswitchB: 1,
}) %}

Here's example code for the buildElementsQuery approach, the problem with this is that
once you've converted to dbCommands you can't go back to a criteria model (which would be
necessary to use the result with Craft's paginate tag for example).

public function myCustomCriteria($criteria, $lightswitchA_value, $lightswitchB_value)
{
    $dbCommand = craft()->elements->buildElementsQuery($criteria);

    $params = array(
        ':lightswitchA_value' => $lightswitchA_value,
        ':lightswitchB_value' => $lightswitchB_value,
    );

    $conditions = array('or',
        'content.field_lightswitchA=:lightswitchA_value',
        'content.field_lightswitchB=:lightswitchB_value',
    );

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

    $results = $dbCommand->queryAll();

    return EntryModel::populateModels($results);
}


Instead of divisableby I think using Twig's built-in odd/even test might be easier in this case:

{% for i in 0.. NbComment %}

   {% if i is odd %}

   {% else %}

   {% endif %}

{% endfor %}

And, just to suggest some minor improvements to your Twig, assuming the only difference between your comments is their alignment (left/right), you could do something like this, which would probably be a bit more DRY:

{% for i in 0.. NbComment %}

{% else %}

No comments to display

{% endfor %}

With the above code, your comments will have either the class .is-odd or the class .is-even – making it easy to e.g. float comments either left or right in your CSS. There's really no need to have a full if/else conditional.

Also, note the {% else %} statement in the above for loop. The contained markup will output if there are no comments – which is good practice, and will save you yet another conditional :)


Element API - Filter on a value from a multi value field

When you wrap your term in asterisks, e.g. *news*, the generated SQL for this query parameter uses a LIKE operator for the ANDWHERE condition is uses (see Element Queries).

Make sure that the values for the Select field don’t overlap (sportnews and news both matching *news*).

'bannerPageCategories' => "*{$target}*"


You can access the assets field by referencing the matrix field first. myMatrixFieldHandle.assets.  So your entries code would be something like this.

{% set entries = craft.entries.section('menu').limit(3).order('RAND()').relatedTo({
       targetElement: assets,
       field: 'myMatrixFieldHandle.assets'
}) %}


I would suggest to already format entryDate within the group filter in the way you actually want to output it later.
To do that use Twig's date filter (→ see all possible formatting options).

{% set allEntries = craft.entries.section('tours').find() %}
{% set allEntriesByMonth = allEntries|group('entryDate|date("F")') %}

{% for month, entriesInMonth in allEntriesByMonth %}

{{ month }}

    {% for entry in entriesInMonth %}

{{ entry.entryDate|date('m.d.Y') }}

    {% endfor %}
{% endfor%}


After some digging, there appear to be two ways that avoid hitting the admin and url query strings.

The first, (and apparently better one, as 'if is evil' according to nginx) uses location handlers:

# 301 Redirect for trailing slash
location ~ ^([^.\?]*[^/])$ {
  try_files $uri @addslash;
}

# 301 Redirect for trailing slash
location @addslash {
  return 301 $uri/$is_args$args;
}

# Root directory location handler
location / {
    try_files $uri/index.html $uri $uri/ /index.php?$query_string;
}

The second, more evil one that uses an if statement:

if ($request_uri !~ "^/admin")
{
    rewrite ^([^.\?]*[^/])$ $1/$is_args$args permanent;
}

I included the context of the root location handler in the first solution so that you can combine it with your existing root location handling setup. I'm currently leaning on a lot of NYStudio's work (a truly incredible contributor to the open source ecosystem of Craft) with FastCGI, location handlers for foreign languages, etc and both of these solutions work with it.

The first also works with query strings, if a user visits a URL either with or without a trailing slash. For example:

This: www.domain.com/page?string=234
Will go to this: www.domain.com/page/?string=234
And this: www.domain.com/page
Will go to this: www.domain.com/page/

Interestingly, if you use query_string instead of is_args for the return url, it will rewrite it wrong. Only is_args worked in my experience.


OK, this was caused by a simple oversight on my part. To simplify matters for anyone else trying to set up Stripe, here is your checklist:
In your templates

Verify that you are using the latest version of JQuery.
Verify that you are NOT using deprecated onLoad. It should be  $('#paymentMethodId').on('load', function(){, not $('#paymentMethodId').onLoad(function(){

At Stripe:

Set up a webhook endpoint. Get your endpoint URL from the Stripe gateway page in Commerce.
Set the webhook to accept "All Events". If you read the docs you can narrow this down considerably.
Copy the webhook signing secret. You will need this for Commerce.

In the Commerce Stripe gateway page:

Enter your publishable and secret API keys.
Enter the webhook signing secret in the Webhook Signing Secret field for the Stripe gateway. Preferably via the .env file like a good Craft citizen.

In your config > general.php file:

Disable CSRF for your webhook URL as detailed here: https://craftcms.stackexchange.com/a/21304/4506

I hope I didn't miss anything.


craft::$app->urlManager->createUrl will always return an action url because in the end this function does return UrlHelper::actionUrl($route, $params);

You want to create a basic site url so you need to do

UrlHelper::url('', ['state' => 'KR'] )


You can use JavaScript to edit the Redactor settings, but the correct answer here is to add the settings with JSON config files. Those should go into your /craft/config/redactor folder.

Take look at the Redactor Styles plugin though – it will add a couple of textareas to your CP for adding custom Redactor JSON and/or CSS, which should make this a bit easier.


Sorting matrixblocks by earliest date from child table

This is a bit tricky to do from the template, but what I would suggest is to query for the Matrix blocks once,
than loop through the blocks and store the data to a new custom array.

The idea is, to build that array in a way that ensures, you can later apply sort and group Twig filters.

{% set allDates = [] %}
{% for block in entry.myEventsMatrix %}
    {% for row in block.myDatesTable %}

        {% set allDates = allDates|merge([{
            datetime: (row.myDateTime|date('c')),
            eventId: (block.id),
            event: block
        }]) %}

    {% endfor %}
{% endfor %}

When sorting an array of arrays with the sort filter, the inner array's first value is relevant, so make sure this is the
DateTime you want to sort by. Besides that, I included the block's ID "eventID" and the complete block model "event".

{% set datesGrouped = allDates|sort|group('eventId') %}

{% for eventId, datesInEvent in datesGrouped %}
    <h3>{{ eventId }}</h3>
    {% for date in datesInEvent %}
        {{ date.datetime|date('Y-m-d') }}
    {% endfor %}
{% endfor %}

Outside the "datesInEvent" loop you can access the events model with:

{% set event = datesInEvent[0].event %}


Entry Count plugin performance / template optimisation

This is untested since I don't have time to load the plugin, so please comment if there is a syntax error but changing this

// get all records from DB ordered by count descending
$entryCountRecords = EntryCountRecord::model()->findAll(array(
    'order'=>'count desc'
));

To something like the following should work

public function getEntries($limit = null)
{
    $where = [
        'order' => 'count desc'
    ];
    if($limit !== null){
        $where['limit'] = $limit;
    }
    // get all records from DB ordered by count descending
    $entryCountRecords = EntryCountRecord::model()->findAll($where);
   ....

And in your template

{% set countedEntries = craft.entryCount.entries(4).section('news').limit(4) %}

Explanation: you include a limit to the query that fetches all entries to load the same amount like the ElementCriteriaModel

Edit: Maybe you have to change this to

public function getEntries($limit = null)
{
    return craft()->entryCount->getEntries($limit);
}


Double escaping Regular Expressions in Craft's Twig replace filter?

Twig auto-escapes the \ character so by the time it makes it to the Craft replace filter PHP code, the regex string looks like /^d+.s/.

By double escaping it, you're forcing the correct regex to make it through /^\d+\.\s/.


Templating - Get a string of the entry's field handle

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

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

myMacro(entry.field2, 'field2').

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

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

myMacro(entry, 'field2').


Navigation Slug Issue (Structure Section)

If the navigation section is strictly for structuring your navigation I would disable 'Entries in this section have their own URLs' and add a entries relation field to connect your content with the navigation items.

A standalone plugin could also help you out: https://github.com/am-impact/amnav


This seems more like it may be an error in your code somewhere, do you have dev mode turned on?

I think you may want to output the title of the category:

'hostingCompany' => (string)$entry->hostingCompany[0]->title,

See if that helps, if not I would update your question with your complete element-api.php


I believe I have a workaround and can (roughly) explain what's going on here.

First, the workaround:

Use array syntax to test the existence of your custom fields instead of object syntax.

{# This works #}
{% if entry['someField'] is defined %} ... {% endif %}

Using array syntax for your conditional will result as true if your field does exist and false if it does not. Using object syntax results in false positives where the conditional always returns true even if a field doesn't exist:

{# FALSE POSITIVES: These return true if a field doesn't exist #}

{% if entry.someField is defined %} ... {% endif %}
{% if attribute(entry, 'someField') is defined %} ... {% endif %}

I believe the false positive occurs using object syntax when the object has or is extending another object that uses a __call() method. Twig will test to see if it can find an attribute or a method.  In the case it can't find an attribute on an object, it will look for a method.  And if it can't find a method on the object, it will check for the existence of a __call() method and if the _call() method exists it returns true, creating the undesired result of also returning true for any variable that doesn't exist on an object that uses a __call() method.

I haven't dug into the code, but it seems that using the array syntax doesn't trigger a search for a potential method associated with the __call() behavior.

A couple related articles can be found on Straight Up Craft:

How to check if a variable or value exists using Twig
Testing if something exists: is defined, length, is not null, is not empty


How do I get Matrix elements to copy their content across language Locales?

Ok, in some conversation with Brandon which leaned this direction, I realized a different direction to temporarily solving most of this problem.

It turns out that a root of the issues is that marking a Matrix as translatable causes the base problem here, that the set of elements in an original language isn't copying at all into other Locales, as would be expected on first Save as all other kinds of elements do.

If you don't mark the Matrix as translatable, two good things happen:

All Matrix elements now do get copied over, so that you don't have to recreate the Matrix in its individual form for each Entry and language.
Text items marked as translatable do have their original text copied over, so that you have a starting situation for language translation

It's true that Assets marked as translatable show up empty rather than with their original content, but at least they are there.

We also don't really know what marking a Matrix as translatable should mean. I suspect it should mean that all contained elements are marked translatable, but we shall see.

The Craft crew is well aware of issues here, and plans a careful improvement of the whole area, which as complex isn't at the top of lists yet.

This little detail should get most of us through until that happens, and given we set up the non-translatability of Matrix elements, should make extra steps explainable to customer end users.


I don't know if anything on AWS can be considered simple, but there is a good writeup on getting Craft up and running with EC2: https://solspace.com/blog/spinning-up-a-craft-cms-development-site-on-amazon-ec2


How to handle custom text on a channel index page?

I'd recommend to either give each channel's index page a dedicated single section or you configure a structure section to contain them all. An advantage of using a structure over separate singles is that you can generate the site's main navigation from it. And you can add a hierarchy to it.

The structure settings in the CP:

URL for Top-Level Entries:
{slug}

URL for Nested Entries:
{parent.uri}/{slug}

You probably want to give your index pages individual templates. To do this just add multiple entry types to your structure and relate each entry type with a template as described in the FAQs.


How to output 'selected' checkbox labels within a matrix

You'd use the checkbox fields much the same way they would be used if they were added directly to the entry and not in the matrix field. Assuming you've got a basic matrix field structure (using if/else or switch):

{% for block in entry.myMatrixField.all() %}

    {% switch block.type %}

        {% case "text" %}

            {{ block.textField | markdown }}

        {% case "image" %}

            {{ block.image[0].getImg() }}

        {% case "checkboxes" %}

            // HELP!!!

        {% default %}

A font walks into a bar.

The bartender says, “Hey, we don’t serve your type in here!”

    {% endswitch %}

{% endfor %}

You could use the same examples that are in the docs and just switch entry for the name of your block variable (block in our case):

Loop through the checked checkboxes:

{% for option in block.checkboxFieldHandle %}
    Label: {{ option.label }}
    Value: {{ option }} or {{ option.value }}
{% endfor %}

Loop through all of the available checkboxes:

{% for option in block.checkboxFieldHandle.options %}
    Label:   {{ option.label }}
    Value:   {{ option }} or {{ option.value }}
    Checked: {{ option.selected ? 'Yes' : 'No' }}
{% endfor %}

See if any checkboxes are checked:

{% if block.checkboxFieldHandle|length %}

See if a particular checkbox is checked:

{% if block.checkboxFieldHandle.contains('optionValue') %}


How do I setup a password administration workflow using setPasswordPath and a forgot password page?

The form that lives at setPasswordPath assumes that the user arrived there by clicking on the link in the validation email that was sent to the provided email address.  That link includes a code=somelongid querystring parameter in the URL that the form is looking for.

If you're just loading that URL directly, then you'll get the "Variable 'code' does not exist" error.  You could always do something like this to guard against it:

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

{% if not code %}
    {% exit 503 %}
{% endif %}

Regarding the forgot password form, upon successfully setting their new password, Craft will check to see if the user has control panel access.  If they do not, it will check the setPasswordSuccessPath config variable and redirect there.  If they do, Craft will send them to the dashboard (which will redirect to the login page if you don't have autoLoginAfterAccountActivation set.


Guest Entries required fields fatal error

This has been fixed in Guest Entries 1.5.1.


How can I expand on a normal Craft query to sort by a column in a custom table?

You can't do this using the craft.entries tag in twig. You'll need to create a new function in your plugin that returns the entries in your custom order.

Assuming you can create an array of element ids in your custom order then the following code should allow you to then fetch entries in that order:

$criteria = craft()->elements->getCriteria(ElementType::Entry);

// filter entries by element ids
$criteria->setAttribute('id', $elementIds);

// order entries by element ids
$criteria->setAttribute('order', 'FIELD(elements.id, '.join(', ', $elementIds).')');

// get entries
$entries = craft()->elements->findElements($criteria);


Does Craft have a server-side queuing system?

Not so much true queues, but Craft does have the (completely undocumented) concept of Tasks, which are meant to be used for potentially long running tasks that don't need to execute immediately.  Plugins can create and register tasks to run.

Here are some questions discussing them:

My tasks don't seem to be running as a background process

How to add a subTask to an already running Task?

Triggering the start of a task from a CRON job

You can view the TaskService in craft/app/services/TaskService.php and you can see examples of Craft's own tasks in craft/app/tasks.

Also worth noting that proper support for queues at the framework level looks like it's on the roadmap for Yii 2.1.


Import Plugin date format (Post Date postDate)

I haven't yet used the plugin, but I'd try to import the dates into another, custom datetime field (e.g. myImportDate) to see if it's a problem with postDate being a special field (also goes into other tables in the DB, as far as I know). This would be for testing purposes only...

Another hint that might help:
Craft usually saves a datetime in a format like so: "2014-07-31 12:00:00". I've no idea if this is relevant for your plugin though. Same applies for the timezone, as Craft saves a datetime in UTC. As the plugin uses the saveEntry API, you probably don't have to care about the timezone, but the string format could break it for you.

Edit:

OK,postDate should be possible and the timezone defined after Craft install should be used to save datetime values. I'd bet it's the unusual "31/07/2014 00:00" format, Simon!


How can I change the size of an individual pin?

Looks like there are a couple of notable errors in your JS:

You have a semi-colon at the end of your icon line. That should be a comma.
On the scaledSize line, you have the colon inside the quote. That should be outside.
Added per Robin's comment... Since you're doing this in JS (not Twig), the new google.maps.Size(32,32) shouldn't be enclosed in quotes. Pass in the JS object directly.

Try something like this...

{% js %}
    var markerId = 'smartmap-mapcanvas-1.{{ entry.id }}.addressInformation';
    smartMap.marker[markerId].setOptions({
        'icon':       '{{ icon }}',
        'scaledSize': new google.maps.Size(32,32)
    });
{% endjs %}


No need for a plugin, just use twig's slice filter, combined with the striptags filter.

I've thrown in the default filter for good measure, in case the body is empty for some reason.

{{ entry.body|striptags|slice(0,100)|default('Read more') }}...

slice will simply output the first 100 characters (starting at 0 the first character), including spaces into the template. striptags ensures that no html tags will be output.


How can I strip or replace a non-breaking space with Twig?

Here's a different spin... Try removing everything that's not numeric or comma.

{{ price|replace('/[^0-9,]/', '') }}


There are a whole bunch of ways to do what you want to do.

You can add custom fields to user accounts. If you wanted to go with option 2 then you could create a custom text field and write the JSON into that.

Another way would be to add a Matrix field to the user accounts and write a new row for each workout.

And another way would be to create a new channel for Workouts. When a user completes a workout, a new entry is created and related to them. You can then retrieve entries relating to that user to display their workout history.

And yet another way, would be to create a custom model for a Workout and relate it to the user account. Your plugin would then create records using that model and you could retrieve them to display the user's progress.


Load Balancing Craft CMS - Admin gets logged out instantly

If you can't enforce sticky sessions, then you'll need to provide a common place for all load balanced web server to save their PHP session files.

By default PHP session files are file based and saved to whatever path the php.ini session_save_path is set to.  You could change that to an NFS share path.

If you had an in-memory key=>value store (like Redis, Memcached, etc.) you could configure PHP to save its sessions there.

If you wanted something more persistent, you could configure PHP to save sessions in a database.

On top of that, if you're not using stick sessions, you'd want to set a consistent appId and validationKey across every web server so they can decrypt Craft/PHP cookies using the same tokens.


Garnish - Event when selecting a category

Try something like this?

$("#fields-myCateogryField").data("elementSelect")
    .on("selectElements", function(e){console.log(e);})
    .on("removeElements", function(e){console.log(e);});


Craft plugin controller for batch update users break with empty page

It was a php.ini config problem, I put some parameters values up and the update succeeded in less than 2 minutes and completed my users batch update.

So you just need to update the values below and reload your web server (ie: Apache).

max_execution_time 120 (instead of initial value 30)
memory_limit 512M (instead of initial value 128M)


It looks like you're missing a closing {% endcache %} tag towards the end of your template.

(See https://docs.craftcms.com/v3/dev/tags/cache.html)

You might also be missing a closing {% endminify %} tag too, but I'm not sure if you've posted the whole of your template or not.


Craft Commerce - For a discount, can we include all products in the product count but not include the sale items that receive the discount?

Based on some research, I believe a custom Adjuster is the way to solve this problem.

I created an adjuster with the following:

craft/plugins/myplugin/MypluginPlugin.php

public function commerce_registerOrderAdjusters()
{
  return [
    401 => new \Commerce\Adjusters\Myplugin_TenpercentDiscount
  ];
}

craft/plugins/myplugin/Adjusters/Myplugin_TenPercentDiscount.php

<?php

namespace Commerce\Adjusters;
use Craft\Commerce_LineItemModel;
use Craft\Commerce_OrderAdjustmentModel;
use Craft\Commerce_OrderModel;

class Myplugin_TenPercentDiscount implements Commerce_AdjusterInterface {

public function adjust(Commerce_OrderModel &$order, array $lineItems = []){

    if (empty($lineItems))
    {
        return [];
    }

    if ($order->totalQty >= 10)
    {
        $adjuster = new Commerce_OrderAdjustmentModel();

        $adjuster->type        = 'Item Discount';
        $adjuster->name        = '10% Off Items';
        $adjuster->description = 'Your order qualifies for a 10% discount on all non sale items because you are purchasing at least 10 products.';
        $adjuster->orderId     = $order->id;

        $amountOff = 0;
        foreach ($lineItems as $item)
        {
            if (empty($item->onSale))
            {
                $amountOff += ($item->subtotal + $item->discount) * .1;
            }
        }
        $amountOff = $amountOff * -1;

        $adjuster->amount      = $amountOff;
        $adjuster->optionsJson = ['lineItemsAffected' => null];
        $order->baseDiscount  += $amountOff;

        $adjuster->included = false;

        return [$adjuster];
    }
    return[];
}

}

Does anyone see any flaws with this approach?


Should project config be used during development when migrating from Craft 2?

I'll answer this for the benefit of anyone else attempting the same thing i.e. sizeable Craft 2 to 3 migration, while you still have the Craft 2 site live.
Ultimately, I chose content migrations and chose to basically ignore the projectConfig functionality for the most part during development. Since I originally asked the question projectConfig changed a bit and got better, rather than it being one big file it is now abstracted out, so it's easier to manage and conflicts are resolved a lot easier now. You previously could disable projectConfig, you actually can't now for the most part, but you can ignore the config/project path at least during development and not check in these files into your source tree, then enable it when you go live and sync the projectConfig files down from production to all environments to then use it going forward.
I chose content migrations because they are repeatable and will continuously test the same logic on any migration run, this verifies for the most part the integrity and conditions that the migration has on each DB migration test and if it fails, it means integrity has failed and it needs to be reviewed.


Figured it out:

    {# Fetch entries with a Matrix block to get non empty categories #}
    {% for block in entry.teamMember.all() %}
    {% set category = block.department.one() %}

        {% if category.title != 'Ownership' %}
{{ category.title }}
{% endif %}
        {% for block in entry.teamMember.relatedTo(category).all() %}

            {% set image = block.photograph.one() %}
            {% if image %}

&nbsp;

            {% endif %}

{{ block.fullName }} {{ block.jobTitle|markdown }}

            {{ block.biography }}

        {% endfor %}

    {% endfor %}


I've found an answer, but I don't know if it's going to cause me any problems or not. Looking at the debug output in the JS Console I noticed that although
$_GET['p'] was set correctly to subpath/directory,
$_SERVER['REQUEST_URI'] was only set to /directory and
$_SERVER['QUERY_STRING'] was only set to p=directory. Maybe Craft or Yii uses the REQUEST_URI rather than $_GET['p'] at some crucial stage?

So I've replaced the $_GET['p']... line in my b.com/index.php with this:

$_SERVER['REQUEST_URI'] = 'subpath/' . (isset($_GET['p']) ? $_GET['p'] : '');

That seems to fix things. Any reason this might be bad and wrong?

UPDATE: Looking back at my code now, it seems that both lines were required, to cover all occasions. So I now have this in b.com/index.php:

$_SERVER['REQUEST_URI'] = 'subpath/' . (isset($_GET['p']) ? $_GET['p'] : '');

$_GET['p'] = 'subpath/' . (isset($_GET['p']) ? $_GET['p'] : '');


Assuming that your products are entries, and comments are related to a product through an entries field, you can use the following:

{% set comments = craft.entries.section('productcomments').relatedTo(entry).all() %}

This uses the relatedTo parameter.

You can then return how many comments are found by using:

{% if comments|length %}
    <p>{{ comments|length }} comments</p>
{% endif %}


Sprout Import: No Changes When Updating Entry

Reasons why it is not updating

The fields data should be wrapped with fields.
If entry is on other site add siteId on params
E.g.

[
  {
    "@model": "barrelstrength\\sproutbase\\app\\import\\importers\\elements\\Entry",
    "content": {
      "title": "Test Import Parent",
      "fields": {
        "body": "Lorem ipsum dolor sit amet."
      }
    },
    "settings": {
      "updateElement": {
        "params": {
          "slug": "test-import-parent",
          "sectionId": 2,
          "siteId": 1
        }
      }
    }
  }
]


"Page not found. What’s worse, a hilarious 404 page can’t be found either."

You need to point your webserver to the public directory as stated in the docs here. So in your case that would mean setting your vhost to point to: User/me/www/Craft-2.3.2644/public.

In that public folder you will find an index.php file, which tells php where Craft can be found, by default (which yours is) that will be ../craft.


Generating thumbnails when using a memcache server for session storage frequently signs users out

My solution to this was to swap memcache for Redis. I realize that doesn't resolve why memcache wasn't working for us, but swapping it corrected this issue.

My best guess is either:

We were caching data to memcache that was too large for it to optimally handle.
Memcache was being overwhelmed when asked to cache the thumbnails for images that Craft was generating.

These are completely unfounded, but just some best guesses on what was happening.


Not all assets copied over when copying an entry from admin panel

Im hesitant to say that this is by design because iam not entirely sure what you mean. Instead i'll explain something i think is comparible that happend to us. We have an entry channel with entries which act as the companies of users on the website. When we saved a company profile in Dutch, fields such as the description or company info would not pull across. We fixed this by listening to the onSaveEntry event and simply pulling the fields across manually. This isnt a very pretty or portable way to do it - but this was an incredibly case and website specific feature - we only wanted entries in this website and even just in this section to have this 'copying' feature. From memory the script looked something like the below:

One word of advise i would issue if of advice i would give is if you are working with other content editors is to listen to the cp.entries.edit.right-pane hook and build a small interface that allows them to select the locale and copy over the current locale to the new locale. The script below has one downside which is that it essentially sterilizes the localization function for craft for the affected entries - which in this projects case was crucial - but in yours probably isnt.

Let me know if anything is unclear. One word of notice - if you are working with a relations field which is what a pdf should be. Relations should be copied over IF you are using something like 'Save as a new entry'. If this isnt happening you've probably found a bug.

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

        // Does the entry section equal our companies section channel?
        if (craft()->isLocalized() && $entry->sectionId == 2) {

                // What locales are there?
                foreach (craft()->i18n->getSiteLocales() as $locale)
                {
                    // Is this a foreign locale
                    if ($locale != $entry->locale)
                    {
                        // Get an entry that belongs to this with a sep locale, setup a model and save it.
                        $otherLocaleEntry = craft()->elements->getElementById($entry->id, ElementType::Entry, $locale->__toString());
                        if ($otherLocaleEntry)
                        {
                            $otherLocaleEntry->getContent()->myFieldsStuff = $entry->getContent()->myFieldsStuff;

                            craft()->entries->saveEntry($otherLocaleEntry);
                        }
                    }
                }
            }
        }
    });


Craft has Craft::log() for that purpose. Brandon has an example of this function over here

To make this work from an external request, you can create plugin with a controller which saves incoming data (post or json) to the log.

To secure this with a key just send an additional variable and check if it's correct.
Take a look at Ben's Dump plugin, for an example of such a key-protected controller.


Custom Module: new element type index page access

Since this is a module rather than a plugin, you need to register control panel template roots, like so:
  Event::on(
    View::class,
    View::EVENT_REGISTER_CP_TEMPLATE_ROOTS,
    function (RegisterTemplateRootsEvent $e) {
        $e->roots['app-module'] = __DIR__ . '/templates/cp';
    }
  );

(I've swapped 'custom' for 'app-module' as I think it's a little more clear, but feel free to keep it as 'custom') If your module's src folder does not have a templates/cp directory, create one and add an index.twig to it. Now going to admin/app-module should load the index file you've created. (You'll need to update the EVENT_REGISTER_CP_NAV_ITEMS from 'custom' to 'app-module' to have the CP url match the change I've made here.) However, since you're working with an element, it's probably better to create another directory named after your element. Let's use "Item" as a generic element class name, you might have templates/cp/items/index.twig who's contents might look like this:
{% extends elementType is defined ? '_layouts/elementindex' : '_layouts/cp' %}

{% set elementType = 'modules\\appmodule\\elements\\ItemElement' %}
{% set title = 'My Custom Items'|t('app-module') %}

{% block actionButton %}

       {{ "New custom item"|t('app-module')}}

{% endblock %}

You don't need to register this URL via the EVENT_REGISTER_CP_URL_RULES, but you will want to for the element edit and creation page. e.g.
Event::on(
    UrlManager::class,
    UrlManager::EVENT_REGISTER_CP_URL_RULES,
    function (RegisterUrlRulesEvent $event) {
        $event->rules['app-module/items/new'] = 'app-module/items/edit-item';
        $event->rules['app-module/items/<itemId:\d+>' => 'app-module/items/edit-item']
    }
);

Here, the key is the URL you will hit in the control panel and the value is the action URL you'll need to create in your module. src/controllers/ItemsController.php, which will have an actionEditItem function.
Hope this helps!


Found cool example of Header Globals what field type is used for this?

Looks to me like a matrix field with 1 block (Navigation) and two fields :

Plain Text - Headline
Table - 2 columns with headings Label (Single-line text) and URL (Single-line text)

It's worth noting that the table field doesn't have a relations column, so they're probably inserting these URLs manually.


Postpone sending activation codes; Creating a user as "Inactive"

Good point, not a very good UX there. We’ll have to come up with something better.


Front-end entry field validation problem

You'll need to make sure the entries title is set otherwise that will throw an error. You can do this using a field in your form or set it in the Control Panel to automatically be set using another field.

Currently you are setting the client field to save using an array with [client][] but the form input is set to text which only provides string values.

This means that when you leave the field blank it uses an empty array as it's value ( [""] ) hence why you don't get the required validation error.

If you want to provide an array of clients you'd need to use a different input type and also make sure that your client fieldType is set to something that can store arrays.

Code suggestion:

<form method="post" accept-charset="UTF-8">

  <input type="hidden" name="action" value="entries/saveEntry">
  <input type="hidden" name="redirect" value="services/{slug}">
  <input type="hidden" name="sectionId" value="3">
  <input type="hidden" name="enabled" value="1">

  Title
  <input type="text" name="title">

  Service
  <input type="text" name="fields[service]">

  Client
  <input type="text" name="fields[client]">

  <input type="submit" value="Submit">
</form>

{% if entry is defined %}

{{ dump(entry.getErrors()) }}

{% endif %}


Yes you can. craft.entries returns an object of type EntryQuery

There is a function matrixBlocks in the CraftVariable that returns an object of type MatrixBlockQuery

Both of them have nearly the same functionality  since they extend the ElementQuery

{% set allMatrixBlocks = craft.matrixBlocks.all() %}


Use Matrix field to output specific html

In your code block.type is the matrix block type, ie homeSlider.

There's alot going on in your code that I'm not sure is intended or not, but let's say you had the fields mainImage and imageText as required fields in there, and have an optional whiteLogo (not sure where that link's suppose to go, it's not in your original html). Try something like this:

{% includeJsFile "/js/jquery.jcarousel.min.js" %}
{% includeJsFile "/js/jcarousel.responsive.js" %}

  {% for block in entry.homepageSlider %}

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

    {% if block.whiteLogo %}

    {% endif %}

{{ block.imageText }}

  {% endfor %}

So, inside you're for loop, the fields you've created are accessible by block.fieldHandle. If you want to make a conditional based on if a field has a value or not, that is done in different ways depending on the type of field. So you'd do {% if block.lightswitchField %} if it's a lightswitch, {% if block.assetField | length %} if it's an assets field, or {% if block.textField != '' %} if it's a text field.

Hope that helps you in the right direction.


Detect currently selected source of custom elements

You can see how this is working by opening craft/app/resources/js/craft.js and searching for the Craft.EntryIndex class definition.

Craft.EntryIndex is an extension of Craft.BaseElementIndex, and is used to govern all Entry indexes in Craft (including Entry selection modals). We pull that off with this line of code, which you’ll find immediately after the class definition:

Craft.registerElementIndexClass('Entry', Craft.EntryIndex);

The logic governing the “New Entry” button is a little complicated, and it relies on an initial version of the button HTML already being available on the page (thanks to the craft/app/templates/entries/_edit.html template), but all the magic happens within its onSelectSource() method, including updating the URL.