group Matrix blocks and also order by Matrix field for a given block

This is a great chance to use the group filter.

First, get all your matrix blocks as an array:

{% set talkBlocks = entry.talks.find() %}

Then group them by type:

{% set talksByCategories = talkBlocks|group('type') %}

At this point, you have an associative array where the keys are the block types, and the values are arrays of the blocks with that type. So talksByCategories.workshop or talksByCategories['workshop'] will be the workshops.

You can group the workshops by round:

{% set workshopsByRound = talksByCategories.workshop|group('workshopRound.value') %}

You should check that there were any workshops first (twig's defined test):

{% if talksByCategories['workshop'] is defined %} ...


Is it possible to prevent disabled Matrix Blocks showing in a Live Preview?

It's definitely a bug in live preview but looks like you can work around it.

This doesn't appear documented at all—so be careful—but you can use .status() to get the block's status. It looks like an IF block is enough to get a matrix block to refresh the live preview.

{%for block in entry.matrixBlock %}
   {% if ( block.type == 'supertable' and block.status == 'enabled') %}
  {#do whatever #}
   {%endif %}
{%endfor %}

I found out about .status out awhile back messing around trying to figure out if there was a good way to display a "sold out" status for a particular show date (for example):

{%for thedate in entry.showDates.type('date').status() %}

    {% if thedate.status() == 'disabled' %}
        {{thedate.showDate|date('m/d/y')}} SOLD OUT!
    {% else %}
        {{thedate.showDate|date('m/d/y')}}
    {%endif%}

{%endfor%}


Localhost: Why does {{ asset.url }} return {{siteUrl}}/path in the browser?

What field type is blog_featured_image? Just an image asset?
Does it work with

<img src="{{ asset.getUrl() }}" alt="{{asset.title}}" /> ?


Perhaps the following plugin could help to import entries from RSS:

Craft CMS plugin to import entries from XML


Getting Entries that were updated after a certain day?

Your criteria for the date updated was written in the wrong syntax. It should be:

$criteria->dateUpdated = '> 2015-09-02';

You can also simplify the way you query your Element Criteria Model like so:

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'affiliates';
$criteria->dateUpdated = '> 2015-09-02';
$affiliates = $criteria->find();

Take a look at the Working with Elements documentation for more info.


You can create your own search...
lets say this is your html

<input type="input" id="searchTags" placeholder="Search">
<input type="button" id="startSearch" value="Go">

then you have the following script:

$("#startSearch").click(function(){
    var data = {
        action: 'pluginhandle/controller/searchEntries',
        options: $("#searchTags").val()
    };
    $.ajax({
       type: "post",
       url: '/',
       data: data,
       success: function(response){
       // replace content from $("#results") with your new html
       },
    ....
   });
});

Your controller would look like

public function actionSearchEntry(){
     $criteria = new ElementCriteriaModel(ElementType::Entry);
     // build your criteriaModel based on your needs
     $html = $this->renderTemplate('results.twig', array(
         'entries' => $criteria->find()
     ));
     return $this->returnJson($html);
}

your results.twig would be like

{% if entries is defined and entries|length %}

        {% for entry in entries %}

                {{ entry.title }}

        {% endfor %}

{% endif %}


Preserve ICC color profile on image transformations

Not currently, but this is already on our list.

The image processing library we're using only recently (within the last 6 months or so) added ICC profile support.

Update:

Great news for all photographers and image lovers! Things changed with Craft 2.3, ICC profiles are now preserved if Imagick is installed and used for the transformation.


What are the Pros and Cons to each image transform technique?

Both methods essentially do exactly the same thing to the image however there are two advantages to pre-defining them in the control panel:

You can just call a transform handle in your templates instead of having to define the whole transform model
They are then available to be used in supported field types e.g. in the Rich Text field type you can select an existing image transform when inserting an image

As you already mentioned the advantages that I can see to defining them in the templates are version control and the lack of needing a database.

I've started defining them all in the templates for the development phase and then when we move to staging I go and add all the ones we're using to the control panel.


You can check the status of an entry with .status. https://craftcms.com/docs/templating/craft.entries#status

This code should work!

{% set jobsEntry = craft.entries.id(jobsId) %}

{% if jobsEntry.status == 'live' %}
    Jobs
{% else  %}
    Jobs is disabled
{% endif %}


How to add a tags-field to an entry form?

You would need to add inputs to the form based on your Tags field handle, with values set to the tag IDs that should be selected.

Here’s a very simple example – it creates a big checkbox list of all the existing tags:

    {% for tag in craft.tags.group('myTagsGroup').limit(null) %}

            <input type="checkbox" name="fields[myTagsField][]" value="{{ tag.id }}">
            {{ tag.name }}

    {% endfor %}

Note that it is not possible to create new tags directly from a Tags field. If you want users to also be able to create new tags from your form, that will require a little Javascript.

+ New tag

Make sure to set the correct groupId in that data object. You can find your tag group’s ID by looking at the URL when editing the group’s settings within Craft’s CP.


Assets Transform returns "Image cannot be found."

A long shot, but if it is indeed a path problem, this has seemed to help me keep my path(s) straight. I my config.php file, I'll set a parameter for environmentVariables like this:

...

'.dev' => array(
    'devMode' => true,
    'siteUrl' => 'http://mysite.dev/',
    'environmentVariables' => array(
        'basePath' => $_SERVER['DOCUMENT_ROOT'] . '/',
        'baseUrl' => 'http://mysite.dev/',
    )
)

...

Then when you are defining your asset sources, you can use this for "File System Path":

{basePath}assets/photos/products/

Then for URL try this:

/assets/photos/products


How to check if an entry is enabled for a particular site?

Based on the anyStatus and site query parameters, it should work like this:

{% set entries = craft.entries()
    .site('foo')
    .enabledForSite(true)
    .all() %}


You put your Redis connection information in your craft/config/rediscache.php config file.  You can see the default here, and your file will override any matching set keys.

From there you can use craft()->cache->set(), craft()->cache->get() and any other cache methods on Yii's CCache class.


Implementing SimpleSAML PHP in Craft plugin

We managed to circumvent the issue by using the sql session storage SimpleSAML PHP also provides. Not a real solution but a viable workaround.


Could I use categories for users instead of user groups?

If the users will never have access to the Craft CP then you can use categories or any other applicable field type (i.e. dropdown, radio buttons, tags, etc.) to create differentiation between the users. It really just depends on how accessible and/or 'static' you want the groups or sudo-groups to be. Categories and tags for example can be created dynamically, without having field editing privileges like a drop-down field would require. But since you are currently the only admin, it probably won't make much difference in the end. I would however, at a minimum create groups that differentiate between users that have different access privileges to the CP, otherwise it's totally up to you — whatever makes most sense and is easiest to manage.


When you take a look at the BookingsController you can see exactly what happens when you need to mark an order as complete

public function actionCompleteOrder(): Response
{
    $this->requireAcceptsJson();
    $orderId = Craft::$app->getRequest()->getParam('orderId');

    $order = Plugin::getInstance()->getOrders()->getOrderById($orderId);

    if ($order && !$order->isCompleted && $order->markAsComplete()) {
        $date = new \DateTime($order->dateOrdered);
        return $this->asJson(['success' => true, 'dateOrdered' => $date]);
    }

    return $this->asErrorJson(Craft::t('commerce', 'Could not mark the order as completed.'));
}

So all you need to do is

$order->markAsComplete();

Which does

$this->isCompleted = true;
$this->dateOrdered = Db::prepareDateForDb(new \DateTime());
$this->reference = 'xxxx';
$this->orderStatusId = y;

You need to set the 4 parameters above to complete an order correctly, not just the isComplete


This is a fairly complex question and this is only really a sketch of an answer.

You'll want to get to know the available models and services in Commerce pretty well to achieve this in all.

You'll most likely do much more work in the plugin side of things than the template side of things - that is, you'll pull together the models/data you want in the plugin, and then pass those things through to the template, rather than just retrieve the data in the template I'd say (as per your example there).

You'd take the various selection paramaters (categories, stock level, whatever) and post these to a controller in your plugin. Then in your plugin, you'd get the variant models you want via PHP, and then post this data through to a template that would render it into a form, and probably just return this whole form via json as some html that you then display with some front end ajax

         $this->requirePostRequest();
         $param1 = craft()->request->getPost('whatever'));

        //This is a service in your plugin that gathers and returns variant models
        $data = craft()->yourplugin->searchStock($param1,...);

       $html = $this->renderTemplate('yourplugin/stockEditForm', array(
            'products' => $data,
        ), true);

        $this->returnJson(["success"=>true, "html"=>$html]);

... in your stockEditForm you then just loop through the products as normal

       {% for product in products %} ...etc

... then some ajax to actually render that on the plugin page

        $.ajax({
        type: 'POST',
        url: '/actions/yourplugin/bulkStockEdit',
        data: form_data,
        success: function(response) {
            $spinner.hide();
            $results.html(response.html);
            $results.show();
        },
        statusCode: {
            500: function(jqXHR, textStatus, errorThrown) {
              $spinner.hide();
              $results.html(jqXHR.responseText);
              $results.show();
            }
        },
    });

That will get you a form with the data populated into it.  From there, each save button in your constructed will need to be hooked up to some ajax to call appropriate Commerce controllers to actually save the changed variants...

I think that, as a basic structure, would get you going with this.  Bulk stock editing certainly would be handy at times!


Front-end searching: Automatically redirect when only 1 result

Redirecting to the first result is simple...

{% if results|length == 1 %}
    {% redirect results[0].url %}
{% endif %}


As noted in the comments, sounds like you've got an error in your Imager config (prob an incorrect value set for the imgixEnablePurgeElementAction option or one of the lines close by).


Force download of asset file from template

I don't think you're going to be able to do this out-of-the-box, but should be stupidly simple with a quick plugin that registers its own Twig extension.  See here for an example.

That extension would add a Twig function that's basically just a simple wrapper for PHP's file_get_contents.

Then from your template, you'd do something like:

{# Get the file contents #}
{% set contents = file('/path/to/asset.zip') %}

{# output it #}
{{ contents }}


Get entry field data via a plugin. ( For specific image assets )

Assuming you already have the entry (see Working with Elements for info about how to do that), you can interact with it exactly the same way you do in your templates - just with PHP syntax instead of Twig.

$asset = $entry->thumbnail->first();

if ($asset)
{
    $url = $asset->getUrl('thumb');
}

Though the transform won’t necessarily be available yet, since getUrl() will not generate transforms that don’t already exist by default.

That behavior can be customized with the generateTransformsBeforePageLoad config setting though, and lucky for you, you can even override the actual config value from PHP before calling getUrl(), using ConfigService::set():

craft()->config->set('generateTransformsBeforePageLoad', true);
$url = $asset->getUrl('thumb');


How many entries could the Craft database hold before it slows down?

It's a bit of a loaded question, but generally it's going to depend more on environmental limitations than anything with Craft itself.

If you're on a shared host along with 200 other accounts using the same MySQL server, then you'll likely notice slowdowns sooner than later.

If you're on a decent host with plenty of memory/disk/CPU available, then we've seen sites with 500k users/entries/assets/etc. running along just fine.

  And is there perhaps a way to automatically delete entries after x amount of time?

As Andrew pointed out in the comments, you could write a simple plugin that exposes a controller action that gets all entries over a certain age and deletes them.  Then you'd setup a CRON job to call that controller endpoint on whatever schedule you want.


There is no native way to limit which sources appear in the asset window. I imagine it can be accomplished with a custom field type. This would be a great feature for future releases; I recommend adding it to the Feature Requests forum.


Can't be done. In short, a template is either extending another template (i.e. it contains an {% extends %} tag anywhere in the code), or it doesn't. Twig doesn't permit the {% extends %} tag inside an {% if %} statement, which makes "conditional extending" impossible.

Using a ternary operation to conditionally select which template to extend is allowed, though:

{% extends item is defined ? "_item" : [entry.locale ~ "/layout", "_layout"] %}

Not sure how you apply the concept of {% extends %}, but personally, I very rarely have more than one "layout" template, and that layout template is fairly stark – usually it'll only contain the stuff that all pages across the site should have, i.e. the basic HTML structure (, global header/footer etc) and global CSS/JavaScript). Sure, some designs require more layouts, but usually that's not where the DRY stuff happens – instead, I tend to use "partial" templates (and macros) a lot, to re-use markup.

Assuming your _layout.html contains the basic HTML framework for your site, and that the entry page and an entry inside a listing is basically the same thing (the former just displays more content), you could do something like this to create a template that works for both listings and single entries:

{# Template /news/index.html #}
{% extends '_layout.html' %}
{% block main %}
    {% if entry is defined %}
        {# Single entry #}
        {% include '_partials/entry' %}
    {% else %}
        {# Listing, pull entries and include the entry partial with a "teaser" flag #}
        {% set entries = craft.entries.section('news') %}

            {% for entry in entries %}

{% include '_partials/entry' with { teaser: true } %}

            {% endfor %}

    {% endif %}
{% endblock %}

{# Template /_partials/entry.html #}
{% set isTeaser = teaser is defined and teaser %}

{{ entry.title }}

    {% if entry.thumbnail|length %}

    {% endif %}

{{ entry.excerpt }}

    {% if isTeaser %}
        {# Just a teaser – display a "Read more" link #}
        Read more
    {% else %}
        {# Not a teaser – render the content in full #}
        {{ entry.body }}
    {% endif %}


Charge plugin: custom actions on webhooks

I don't see events being triggered in the Actions Service (in my version of Charge anyway), so you won't be able to listen for those. You'll most likely have to modify the core, if you do, document that and when you update charge, you can easily put your modifications back into place or do a pull request to charge in hopes that event gets added to the core.


Accessing SEOmatic meta via controller action in Element API triggers HTTPForbiddenException

Probably you need to turn on the Meta Container Endpoint Access option in SEOmatic -> Plugin Settings -> Endpoints
This is intentionally disabled by default, you need to enable it if you intend to use it.


Those aren't so much errors as deprecation messages, meaning you should fix them sometime before Craft 4 comes out where they'll be going away and become real errors for you. :)

  To which I assumed I should just add 'securityKey' => 'xxxxxx', but the error hasn't gone.

They won't go away automatically.  Go to yoursite.com/admin/utilities/deprecation-errors, then you can click the "x" for the message on the far right to clear it.  It won't come back again if it has been fixed.

  The environmentVariables config setting has been renamed to aliases.

You'll want to convert your old environmentVariable to use the new aliases syntax.  You can see examples of that here:

https://docs.craftcms.com/v3/configuration.html#aliases


Is it possible to duplicate a entry as a draft entry?

You can refer to this How can I copy an entry?

Just change:

$newEntry->enabled = $oldEntry->enabled;

to

$newEntry->enabled = false;

To start out building your own plugin: https://pluginfactory.io/, be sure to select the Services lightswitch.


Assuming yourLightSwitchFieldHandle is labeled "Hide From Logged Out Users", something like this should work.  Completely untested.

{# if the user is logged in OR they are not logged in but we don't want to hide the current product #}

{% if currentUser OR (not currentUser and not yourProduct.yourLightSwitchFieldHandle) %}
        Show Product
{% endif %}


Caching ElementCriteria Lookups In Craft CMS Plugins

I have figured it out, but am not sure if this is the best way so could still use some advice.

# Get a unique hash of your search criteria (still figuring this out).
$hash = md5(json_encode($projectCriterea));

# Look up the cache
$cache = craft()->cache->get($hash);

# Did we find this search criterea in the cache already? If so, return it.
if ($cache) {
    return $cache;
}

# No cache? Do searchy business
# ...
$projects = $projectCriterea->find();
# ...

# Save to the cache
if ($cache === false) {
    craft()->cache->set($hash, $projects, 604800); # Cache for 1 week
}

return $projects;


Setting relative path to ElementAPI in PHP

You need the url, not the file path. Can you store the url, or the http://localhost:8888 part of it in an environment variable? That gives you
$url = getenv('CRAFT_URL') . $id . ".json";

If it is not already in an environment variable, then in a .env file? web/index.php that comes with Craft is a good example of loading a .env file, and then using the environment variable.


Maybe you could pull it off with some CSS/JS hackery, but it'd be pretty sketchy.

The navigation bar used to be at the top of the Control Panel up until Craft 2.5 came out.  The screenshots you're seeing are probably of the older versions of Craft.


error in production when using redis for cache and session

Luckily, someone else had this problem: https://github.com/craftcms/cms/issues/7617#issuecomment-786715807
The issue was because of leaving the password blank. devMode did not care, but production did. Had to remove the password entirely


Is the "registerSiteRoutes" hook screwing up my template path?

Craft will only check for templates in your plugin’s templates/ folder during CP and action requests. When you start routing to your controller action via a site-facing route, it’s no longer either one of those; it’s just a normal Site request. So you will need to point Craft to your plugin’s templates folder explicitly.

// Point Craft to this plugin's templates/ folder
$templatesPath = craft()->path->getPluginsPath().'myplugin/templates/';
craft()->path->setTemplatesPath($templatesPath);

// Render and output the template
$this->renderTemplate('_mytemplate', $variables);

Note that it will no longer be necessary to include your plugin’s handle in the template path.


Posting comment as answer, since the suggested solution solved it:

Pass the IDs as an array instead of comma separated: {% set thisCalendar = [3,2] %}


If you're simply looking to execute some custom scripts that are completely standalone (i.e. they don't interact with the Craft application in any way), those files should live somewhere below your public web root (i.e. the public folder, or wherever your index.php file resides). It isn't possible to have Craft route PHP files from the /templates directory.

However, the problem with reading/executing arbitrary PHP files from the public root, is that Craft basically "hijacks" all requests to anything below that folder, and routes those requests to index.php. In order to read or execute an arbitrary PHP file below the public root, you'll need to override Craft's URL routing, for example by using RewriteRule directives in your .htacesss file if you're using Apache (also see this related thread).

On the contrary, if your custom PHP scripts do need to interact with Craft in any way, you'll need to write a custom plugin.

Fortunately, Craft plugins are relatively simple to build (as long as you're familiar with PHP, of course). You can use the excellent Plugin Factory to quickly scaffold a bare-bones plugin with a thoroughly commented codebase or use the Business Logic plugin as a starting point. Downloading other available plugins and looking at their source code is probably not a bad idea, either.

In any case, before digging in you should definitely skim through the official docs on plugin development. By far, the most important thing to know about Craft plugins is how they are structured and what the various moving parts do. That knowledge will also give you a nice overview of what a plugin's capabilities are, and how you'd go about implementing a certain feature in your own plugin.

One thing that the official docs doesn't really mention, which might be relevant to your use case, is how you make use of third party scripts or libraries. There are lots of ways to skin that particular cat, but the headline is that using using Composer if you can is the best option, though a simple require() call in your plugin's main class' init method will of course also work.

Also, keep in mind that when you're using third party scripts inside a Craft plugin, you will need to deal with namespacing.

Edit

The upcoming Craft 3 release adds another option for running PHP business logic – Yii2 Modules.


Login Modal - How to handle incorrect password / credentials?

You may use some ajax to send your form so your modal will not validate and/or close and your page wont reload.

Here's a working example of what you will need to do in JS (this example use jQuery):

$('#yourFormId').submit( function (e ) {
      e.preventDefault();
      var data = $(this).serialize();
      $.ajax({
        method: 'POST',
        url: '/',
        data: data,
        headers: {'Content-Type': 'application/x-www-form-urlencoded'}
      })
    .success(function(data) {
          console.log('success', data);
    })
      .error(function(data) {
        console.log('error', data);
      });
    });

If validation errors happen, you will see that in the data object folowwing the .error.


Is there a way to retrieve the type of an entry?

The structure type is stored in the section, not in the entry type. entry.type doesn't return the name, it returns the entry type as an object

{% set structureType = entry.getSection().type %}

It will return a string that can have the following values.

const TYPE_SINGLE = 'single';
const TYPE_CHANNEL = 'channel';
const TYPE_STRUCTURE = 'structure';


What causes an entry's field to be marked as "modified" when the entry is saved?

When an Edit Entry page is loaded, Craft takes note of all the fields’ current form values, and when the form is submitted, only field values that have changed will be posted. As far as the back-end is concerned, if a field is included in the post data, then it was changed; otherwise it wasn’t.

I suspect that the modified param you are seeing is a Neo-specific thing. Sounds like maybe they have their own change tracking going on, which is separate from how Craft does it.


How can I test if a field has been assigned to a channel?

Twig has a "is defined" test that you can apply to a variable to see if it exists:

{% if entry.possibleField is defined %}
    Yup!
{% else %}
    Nope!
{% endif %}

And here is more information on using is defined.


Nope, not currently... though there is a feature request for it:

  http://feedback.craftcms.com/forums/285221-feature-requests/suggestions/9009169-add-an-alert-or-warning-when-multiple-authors-are

I guess it's possible for it to be done in a plugin, although I'm struggling to picture exactly how. At this time, no such plugin exists.


Set default status in CP admin for queried entries from "All" to "Live"

After a little head-scratching, the only way I could get this working was to register an AssetBundle (to load in my own JS), and making use of the Garnish toolkit as follows:

$(document).ready(function() {
    var statusSet = false;

    Craft.elementIndex.on('updateElements selectSource', function(data) {
        if (!statusSet) {
            // Find the option (and make sure it actually exists)
            $option = data.target.statusMenu.$options.filter('a[data-status="live"]:first');

            if ($option.length) {
                data.target.setStatus($option.data('status'))
                statusSet = true;
            }
        }
    });
});

This should only trigger the setStatus() process once, even when navigating between sources (which will also be filtered to to the saved status state of "Live"), but allows the user the freedom to change the status again if they so choose.

I hope this helps :)


I assume you're using .search() – a common mistake is to try to combine orderBy('score') with custom fields, which doesn't work because the score attribute isn't an actual field, but a computed value that Craft "injects" into the element model.

If I understand you correctly, you want to render any "featured" entries at the top of the search results. You could achieve this by doing two separate search queries, before merging the results, with the featured entries at the beginning of the entry results array. Assuming featured is a Lightswitch field, something like this should work:

{% set searchQuery = craft.entries.search('foo').orderBy('score') %}
{% set featuredEntries = searchQuery.featured('1').all() %}
{% set notFeaturedEntries = searchQuery.featured('not 1').all() %}

{% set allEntries = featuredEntries|merge(notFeaturedEntries) %}

{% for entry in allEntries %}
    ...
{% endfor %}

If you need to use pagination, the above won't fly – in which case you could opt to just collect the entry IDs and do a third query to pull the full entry models for a paginated result set:

{% set featuredEntryIds = searchQuery.featured('1').ids() %}
{% set notFeaturedEntryIds = searchQuery.featured('not 1').ids() %}
{% set allEntryIds = featuredEntryIds|merge(notFeaturedEntryIds) %}

{% paginate searchQuery.featured(null).limit(10).id(allEntryIds).fixedOrder(true) as pageInfo, pageEntries %}

An alternative approach to the above is to just have a single query, and use the group filter to sort out the featured entries from the non-featured ones:

{% set entries = craft.entries.search('foo').orderBy('score').all()|group('featured') %}
{% set featuredEntries = entries['1'] ?? [] %}
{% set notFeaturedEntries = entries[''] ?? [] %}

Note: If you're using Craft 2, be sure to replace the orderBy parameter with order. Using order in Craft 3 will still work, but the parameter is deprecated and will not work in Craft 4.


Are you wanting to drag entries up and down to sort them? As far as I'm aware the only way to order manually would be to use a Structure and not a Channel.

Alternatively if you just want to manually order them for use in a for loop (such as showing news items), you could add an entries field somewhere (in a global, a news page, a homepage, or somewhere else convenient). Then you can reference that list for your entries output. That would let you manually order them.


Had missed copying over a hidden .env file. Once I copied over to server, install completed. Thanks to all who commented..


How can I store Craft sessions in the database?

To store sessions in the DB in Craft 3, you can merge the following into your config/app.php file:

return [
    'components' => [
        'session' => [
            'class' => yii\web\DbSession::class,
            'as session' => craft\behaviors\SessionBehavior::class
        ],
    ],
];

Then you need to manually create a session table in your database. Here's a mysql migration:

CREATE TABLE session
(
    id VARCHAR(255) NOT NULL PRIMARY KEY,
    uid VARCHAR(255) NOT NULL UNIQUE,
    expire INTEGER,
    data BLOB,
    dateCreated TIMESTAMP NOT NULL,
    dateUpdated TIMESTAMP NOT NULL
)

I wrote the Craft 2 DB sessions plugin referenced in the question. The Craft 3 approach is much nicer.


.relatedTo() not returning tags with spaces

In your working example, you’re mapping request.tags to the search param, but in the non-working example, you’re mapping it to the slug param.

Those two params are handled in very different ways. search will do some normalization routines on the value, and perform a very loose search for those keywords (see https://craftcms.com/docs/searching for more details). But the slug param will actually look for an exact match.

So if request.tags is set to "low confidence" and you pass that value into a slug param, I have complete confidence that it will return zero results, since "low confidence" isn’t actually a valid slug (see what I did there?).

You would have slightly better luck passing request.tags through the kebab filter, which will make the value look a little more like a valid slug. But the search param is probably a better bet unless you know for sure that request.tags is actually going to be a slug.


That Straight Up Craft article is pretty old and based on the Redactor I API, I believe.

Pretty sure in Redactor II, formattingTags got replaced with either formatting or formattingAdd, depending on your needs.


How do I use URL parameters to filter a channel by a date field?

You can pull query string variables using the HttpRequestService, like this:

{% set month = craft.request.query('month') %}
{% set year = craft.request.query('year') %}

Then, you'll need to construct a DateTime object from those query parameters:

{% set queryDate = date([month, year]|join(' ')) %}

...and finally, include that date object in the criteria for craft.entries (notice the >= operator, which means we should get entries with a availabilityStartDate value equal or higher to the queryDate date object:

{% set allEntries = craft.entries.section('availability').order('availabilityStartDate').availabilityStartDate('>= ' ~ queryDate.date).limit(null) %}

EDIT

Filtering out entries with date field values matching the queried month and year exactly is a bit more complicated.

There are probably several ways to approach this, but a thing that works is to use both a start date (i.e. the first day of the queried month) as well as an end date (i.e. the last day of the queried month) for the criteria.

Being that the queryDate variable actually already refers to the first day of the queried month, we'll just need to add 1 month for the end date:

{% set queryStartDate = date([month, year]|join(' ')) %}
{% set queryEndDate = queryStartDate.date|date_modify('+1 month') %}

And here's the element criteria with both date object statements:

{% set allEntries = craft.entries.section('availability ').order('availabilityStartDate').availabilityStartDate('and', '>= ' ~ queryStartDate.date, '< ' ~ queryEndDate.date).limit(null) %}

Here's everything together, for cohesion:

{# Get month and year query parameters #}
{% set month = craft.request.query('month') %}
{% set year = craft.request.query('year') %}

{# Create DateTime objects for the start date and end date (+1 month) #}
{% set queryStartDate = date([month, year]|join(' ')) %}
{% set queryEndDate = queryStartDate.date|date_modify('+1 month') %}

{# Get the entries #}
{% set allEntries = craft.entries.section('availability ').order('availabilityStartDate').availabilityStartDate('and', '>= ' ~ queryStartDate.date, '< ' ~ queryEndDate.date).limit(null) %}

PS: When you have multiple parameters to craft.entries like this, you might want to consider the object syntax for readability:

{% set allEntries = craft.entries({
    section : 'availability',
    order : 'availabilityStartDate',
    availabilityStartDate : 'and, >= ' ~ queryStartDate.date ~ ', < ' ~ queryEndDate.date,
    limit : null
}) %}


Comprehensive logging of user actions with Craft Pro?

I don't know of a plugin that exists expressly for this purpose, but you could combine LumberJack (logging plugin) with Craft's numerous events to make this happen with your own plugin. You can log from within said plugin or even in your Craft templates.

Take a look at the event reference and see if there's enough there to satisfy your client's needs. Creating your plugin should be pretty straightforward.

It may also be worth noting that Craft's logs are available from the control panel at /admin/utils/logs. These are developer-centric errors and warnings though, not a record of specific user actions.


Contact Form Plugin: Validate if a checkbox is checked?

There's no clean way doing this without making changes to the plugin itself. The  contactForm.beforeSend event makes it possible to prevent the email from being sent from another plugin, but you're only being passed the compiled email message as a string. It's probably possible to post you checkbox data with that string and parse for it in your event listener, but you asked for a clean solution! :)

So fork the plugin and add a new attribute to the ContactFormModel:

'agreedToTerms' => array(AttributeType::Enum, 'required' => true, 'values' => array(true)),

And make the ContactFormController get the attribute value from your form:

$message->agreedToTerms = craft()->request->getPost('agreedToTerms');

You're now all set add a checkbox "agreedToTerms" to your form and add a custom error message in case the model attribute failed validation:

<input type="checkbox" name="agreedToTerms" value="true" {{ message is defined and message.agreedToTerms ? 'checked' }}> Agree the Terms and Conditions

{% if message is defined and message.hasErrors('agreedToTerms') %}

{{ 'You must agree the Terms and Conditions'|t }}

{% endif %}


first() don't seem to work while using an image transform

This is where it goes wrong:

{% for asset in image %}

Because you use first(), you end up with an AssetFileModel, not an array of those.
If you than loop through that AssetFileModel with a for-loop, you get all the values of that Model. They don't have a method called getUrl(), which is what causes the error.

So, skip the for-loop and just use:

{% set image = entry.articleImages.first() %}
<img src="{{ asset.url('worksList') }}" />

The url() method is an alias for getUrl().


Image Transform of Transparent Images results with Black Background

I was able to remedy this with a plugin (requires ImageMagick)
https://github.com/aelvan/Imager-Craft#bgcolor-string


Can we log both access & content changes?

Craft does some basic logging in the form of when an entry was updated/created and the last time a user logged in and from what IP address, etc.  If you want anything more detailed than that, you'd need a plugin.  There is one called Audit Log that might do what you're looking for.


How to fetch all assets that are in use, via a specific field

You can use Relations to find assets which are related to a set of entries (i.e. used in a field of the entries). Specifically, the relatedTo parameter allows you to limit an asset query to assets that are used in a specific entry or set of entries. One caveat is that you have to load the entries which contain the assets field first (at least as far as I can tell from the documentation).
So you need to queries, one to get all entries with assets on them and one to get all assets:
$teams = Entry::find()
    // replace with the name of the section your asset field is used on
    ->section('teams')
    // replace with name of your image field; find only entries with images in your image field
    ->my_image_field(':notempty:')
    ->all();

$assetsUsedInTeams = Asset::find()
    ->relatedTo([
        'element' => $teams,
        'field' => 'my_image_field',
    ])
    ->all();

Now getting the titles of entries where the asset is used is slightly more involved. You can use the same approach, but you will probably need another query for each image to find related entries. For example:
foreach ($assetsUsedInTeams as $asset) {
    $entriesContainingAsset = Entry::find()
        ->relatedTo([
            'targetElement' => $asset,
            'field' => 'my_image_field'
        ])
        ->all();
}

Not sure about that last query, might need some adjustments to work properly. Also, those are a lot of N+1 queries, so once it's working as you want it to make sure to optimize your queries with Eager-loading and maybe add some caching as well.


Craft News Feed not working after 2.5 Update

Just checked 2 upgraded sites of me and to me it's working..


500 Internal Server Error when accessing admin

It turned out that RewriteBase / needed to be added to the htaccess


Returning entries based on Relationships across different category groups using 'and'

After some help from @RobinSchambach on the Craft Slack and a bit of trial and error I got to this, truncated for brevity.

{# clear everything #}
    {% set colourQuery = '' %}
    {% set sizeQuery = '' %}

    {# get all the search query parameters #}
    {% set colour = craft.request.getParam('colour') %}
    {% set size = craft.request.getParam('size') %}

    {% set colourQuery = colour | join(',') %}
    {% set sizeQuery = size | join(',') %}

    {# colour #}
    {% set colourParams = ['or'] %}
    {% set cats = craft.categories.group('colour').slug( colourQuery | split(',') ).find() %}
    {% for cat in cats %}
        {% set colourParams = colourParams | merge([{ targetElement: cat }]) %}
    {% endfor %}

    {# size #}
    {% set sizeParams = ['or'] %}
    {% set cats = craft.categories.group('size').slug( sizeQuery | split(',') ).find() %}
    {% for cat in cats %}
        {% set sizeParams = sizeParams | merge([{ targetElement: cat }]) %}
    {% endfor %}

    {# build criteria #}
    {% set relatedParams = ['and'] %}
    {% if colourQuery != '' %}
        {% set relatedParams = relatedParams | merge([{element : colourQuery}]) %}
    {% endif %}

    {% if sizeQuery != '' %}
        {% set relatedParams = relatedParams | merge([{element : sizeQuery}]) %}
    {% endif %}

The key difference is that I'm using the Category IDs rather than their slugs. I'm then passing them as comma delimited strings into the array to build up the criteria.

I'm working on refining this a bit more but it's now working as expected.


Why is Sprout Forms returning 302 for ajax requests?

First I want to say thank you to the support staff at Sprout for helping me figure out my error.

I have the default install settings/configuration for a Sprout form. Spam protection was enabled in my case and that's what was causing the 302.

If I want to have spam protection enabled, I need to have this inside my <form> tags:

{% hook 'sproutForms.modifyForm' %}

So my form looks like this now:

<form id="contact-form" method="post" class="main-form" accept-charset="utf-8">
    <fieldset>
        {% hook 'sproutForms.modifyForm' %}
        {{ csrfInput() }}
        <input type="hidden" name="action" value="sprout-forms/entries/save-entry">
        <input type="hidden" name="redirect" value="{{ form.redirectUri|hash }}">
        <input type="hidden" name="handle" value="{{ form.handle }}">
    </fieldset>

    <fieldset>
        {# Get the full name field. #}
        {% set fullName = form.getField('fullName') %}

        ...
    </fieldset>
</form>

I'm getting a 200 response back and the entry is getting created!


Trouble getting a list of categories that have entries for a specific category group

I would reverse your logic:

get all entries in whatever channel
display only categories (from a certain group) that have entries fetched in step 1 attached to them

Something along the lines of:

{% set entries = craft.entries.section('myChannel').limit(null) %}
{% set activeCategories = craft.categories.group('myCatgroup').relatedTo(entries).find() %}

You can then use a simple for loop to display only the active categories


Add variable to purchasable variant to modify price?

I think Multi Add will be the simplest approach here - it really won't be hard with that, and Luke repeated recently that multi-add will become core, so apart from some possible minor template modification later, it seems a sensible way to build this - and will be simpler (going forward as  well) than writing a new plugin for it, where you'll have to take a lot more care with your extra logic for shipping/tax etc.  Multi add just adds multiple products, but leverages core ine very other way, so it's a very robust solution.


How get entries between mutiple dates, ordered by date?

Perhaps you could use the Preparse Field plugin, so that you only need to deal with one field. That would make the query easier.
https://plugins.craftcms.com/preparse-field


Entry Form: Populate checkbox list from another entry and save options in entry

Could this be a reserved word? Generally I access fields using entry.registeredOccurances is there a reason you are using fields[registeredOccurances] and entry[dateFieldHandle]?


How can I get a list of unique products a Craft Commerce customer has purchased?

Something like this should work:

{# Grab the currently logged in users past orders %}
{% set pastOrders = craft.commerce.orders.customer(craft.commerce.customer).find() %}

{% set uniqueSKUs = [] %}

{# loop through the orders #}
{% for order in pastOrders %}

    {# loop through the line items #}
    {% for item in order.lineItems %}

        {# did we find a unique one? #}
        {% if item.purchasable.sku not in uniqueSKUs %}

            {# add it to the list #}
            {% set uniqueSKUs = uniqueSKUs|merge([item.purchasable.sku]) %}

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

Unique SKUs for customer ID {{ craft.commerce.customer.id }}:

    {% for sku in uniqueSKUs %}

{{ sku }}

    {% endfor %}


This is the solution

$('.CodeMirror > div > textarea').attr('readonly','readonly');

in init{} redactor calback


How to create an Asset Source programmatically via a plugin?

I don't think you can add asset source types without modifying core. The list of components that is allowed / scanned for does not contain AssetSourceTypes.

Unless you mean create an asset source using an existing AssetSourceType programmatically?

If you want an asset source saved, I would guess it is similar to below:

$source = new AssetSourceModel();
$source->name   = 'Source name';
$source->handle = 'Source handle';
$source->type   = 'Local';
// Not sure about the settings here
$source->settings = array('path' => 'path/to/','url' => 'url/path/to', 'publicURLs' => '1');

$fieldLayout = craft()->fields->getLayoutById(1); // set this to the field layout you want
$fieldLayout->type = ElementType::Asset;

$source->setFieldLayout($fieldLayout);

if (craft()->assetSources->saveSource($source)) {
    // Success saving
}
else {
    // Error saving
}

You can look at the AssetSources controller actionSaveSource for reference.

There are some areas I'm not sure about such as the settings and the field layout, as they get set by POST data, but this should lead you in the right direction.


Loop through entries in a Matrix block type

I'm assuming you are talking about your block type having a Entries field within.

You simply loop through it like this:

{% case 'BlockType3' %}

{% for entry in block.entriesFieldHandle %}

{{ entry.title }}

{% endfor %}


I can confirm that Win8.1 + PHPStorm + xDebug and plugin code works fine.

Are you symlink'ing (using mklink in Windows) to your plugin code by chance? xDebug won't follow symlink's by default and at least in PHPStorm, you have to explicitly setup the path mapping in your project's settings to tell PHPStorm/xDebug where the actual paths to your symlink'ed files live.


It could be your server blocks outgoing mail on the default port (25). Try port 587 instead.


After much head scratching it wasn't an SSL issue. Litespeed had recently been installed on the shared server but was misconfigured.

  It appears the allowed header size default value was modified during
  the installation of LiteSpeed which caused the issue. We've now
  restored the default value and the functionality of the website
  appears to have come back.


I believe the answer is to roll my own archiving method – archived elements results in them not being accessible in element indexes.


What's the best practice for upgrading a versioned Craft site?

I know your method works flawlessly, but it scares the crap out of me.

Luckily Craft's update setup is magical.

What I do is this.

Make sure my repo is clear of unstaged files, just so the update can be in a commit all by itself.
Run the update on my local dev environment (with a local database) (Test)
Commit the updated files and push
Backup live database just in case
Deploy the files on live. (I use Beanstalk, so it uploads the files for me, but you can also do a git pull if that's your method of deployment.) Craft detects that the database version doesn't match the files and puts up a maintenance message.
Visit /admin and click the update button
Drink.


Any problems installing Craft on CentOS with SELinux enabled?

Someone with more CentOS experience will probably want to chime in—like you I'm more familiar with Debian/Ubuntu—but I can't imagine it wouldn't work, assuming you configure SELinux correctly and you're using at least CentOS 6, preferably the latest.

Basically, SELinux is an kernel level gatekeeper, preventing or allowing certain processes from reading/writing to parts of the file system.

In terms of how that affects Craft, you'll need to make sure it knows that Apache/PHP is allowed to write to /craft/app, craft/config and craft/storage and whatever upload directories you have setup.

Just perusing the SELinux docs and problems people have had with Yii and WordPress, assuming your Craft install is at /var/www/craft/ running something like:

cd /var/www/craft/
chcon -R -v -t public_content_rw_t app/ config/ storage/

... should open up the permissions. There's more to it than that obviously.

If you run PHP as an FPM pool/CGI, as I do, that's going to affect permissions as well.

This article is based around setting up permissions for WordPress but it's still applicable for Craft.


How do I show errors for a new front end entry form?

Thanks to a teammate, got this working!

Needed to change the conditional wrapping my error messages from

{% if entry is defined %}

to

{% if entry is defined and entry is not null %}


Can you extend "_layouts/cp" in a plugin settings page?

Your settings page doesn't need to include {% extends "_layouts/cp" %}.

Also there's no need to define any block section. What's in your template/settings.html file will be shown within that CP-area per default.


Creating a POST request endpoint using Element API

You might want to check out this plug-in:
Restful Api

Restful Api is a plugin for Craft CMS that exposes elements as resources via a restful api. While similar to Craft's own Element Api plugin, Restful Api offers a few more features such as support for more HTTP verbs, authentication and element type based permissions.
Restful Api utilizes Fractal to transform and serialize responses. Restful Api is also PSR-7 complaint. Its request and response objects can even be utilized by third party plugins if desired, although this has not been extensively tested yet.


How to set and test a variable in child template to modify a block in parent template

Nope, that's not going to work unfortunately, due to the way scoping works in Twig. Check out the explanation in the Twig Processing Order & Scope article


Not exactly sure what you are trying to do with this data, but it sounds like you could use the group filter

{% set alphaEntries = craft.entries.section('shops').type('shops').all() | group('title | slice(0, 1)') %}

{% for letter, entries in alphaEntries %}

{{ letter }}

        {% for entry in entries %}

{{ entry.title }}

        {% endfor %}

{% endfor %}


Using relative paths for assets for heroku deployment

Take a look at Multi-Environment Configs and specifically environmentVariables. Then you can add your variables to the settings in the Craft CP.

Note: you'll have to figure out Heroku's paths by trial and error or ask their support staff for help.


If you want to leave the data as-is, you could just fetch the “related” interaction entries like this:

{% for interaction in craft.entries.section('interactions').relatedPostSlug(enry.slug) %}
    {{ interaction.comment }}
    ...
{% endfor %}


Edit: I've misunderstood the question! It sounds like Schools aren't related Elements, but just a dropdown value?

I think there are a couple of missteps, here:

The .group() method on a UserQuery actually applies a filter, narrowing the results by a User Group with that handle. (Maybe that's understood, but I wanted to note the difference between this and the next couple of notes!)
(An aside that will help optimize this for #3) I recommend eager-loading your related School elements by calling .with(['schoolAttended']) on your main User query.
The | group(…) filter takes an array and groups it by a property, closure, or Twig expression. In this case, I think you actually want to be more explicit about how the grouping is happening, so I'd use | group(u => (u.schoolAttended | first).id). This ensures the key used for grouping is consistent and unique.
usersBySchool.all() is calling the .all() method on an array, which won't work (it'll only be present on ElementQuery instances)—your Elements are already loaded after the first statement, and grouping just takes the resulting array and re-organizes it! This for loop should probably just be: {% for schoolId, athletes in usersBySchool %} … {% endfor %}.

So, altogether:
{# Load all “athlete” users: #}
{% set athletes = craft.users({
  group: 'athlete',
  with: ['schoolAttended']
}).all() %}

{# Group by their School's ID: #}
{% set athletesBySchoolId = athletes | group((u) => (u.schoolAttended | first).id) %}

{# Fetch Schools and index by ID. Note that we have the IDs ready, via the grouping operation, above—we can just take the keys off that array! #}
{% set schoolsById = craft.entries({
  section: 'schools',
  indexBy: 'id',
  id: athletesBySchoolId | keys
}).all() %}

{% for schoolId, athletes in athletesBySchoolId %}
  {# Look up the school for this group via our secondary Schools query (which, again, is indexed by ID): #}
  {% set school = schoolsById[schoolId] %}

{{ school.title }}

    {% for athlete in athletes %}

{{ athlete.getFullName() }}

    {% endfor %}

{% endfor %}


This would have to be a plugin to pull in an rss feed and make it an entry -butt there is also the option to use the craft.feeds tag to pull rss feeds directly into your template.

http://buildwithcraft.com/docs/templating/craft.feeds


How to route 404 errors for multi-site Craft?

I pondered this for a while, and then did this, which will direct us to specific entries (not templates, I don't want to create more of those):

{# We need a unique 404 for each site - just take us to the
   right slug relative to current URL #}

{% switch currentSite.id %}

{# siteA.com #}
{% case 1 %}

    {% redirect '/my-404-slug' %}

{# siteB.com #}
{% case 2 %}

    {% redirect '/my-other-404-slug' %}

{% endswitch %}

If you want to use templates instead of entries, just use an {% include %} statement instead of {% redirect %}.


If you've got a dropdown field defined with no value as one of the options, it should be as simple as:

{% if entry.dropdownFieldHandle %}
    {{ entry.dropdownFieldHandle }}
{% endif %}


Is it possible to use set the locale manually in a template?

Completely, 100% untested, but I think you'd be able to pull it off with a pretty simple plugin that added a new Twig filter (check the Twig Extensions switch).

From a template you'd something like:

{{ myDate|myDateFilter('es') }}

Then your plugin's myDateFilter method would do something like:

public function myDateFilter(\Twig_Environment $env, $date, $locale)
{
    $localeData = craft()->i18n->getLocaleData($locale);
    $dateFormatter = $localeData->getDateFormatter();

    return $dateFormatter->formatDateTime($date->getTimestamp());
}


Find entries with multiple categories with an and/or twist

Ok, I was close :P

The trick is to create an object to pass instead of an array. The documentation for this is sketchy and confusing so I hope this snippet helps someone.

Notice I am setting 'and' at the root of the object, but this only applies to the objects that follow, not to targetElement arrays. So by separating all the features into separate objects, the 'and' is applied to them, but not the models.

{% set models = [24, 25, 26] %}
{% set features = [46, 47, 48] %}

{%
  set relatedTo = ['and', {
    targetElement: models,
    field: 'model'
  }]
%}

{% for feature in features %}
  {% set relatedTo = relatedTo|merge([{
    targetElement: feature,
    field: 'feature'
  }]) %}
{% endfor %}

{%
  set entries = craft.entries({
    relatedTo: relatedTo
  })
%}


Since you said this “page” is merely a link to an external site, you’re not going to see it in the Entries section of the Control Panel. Most likely this page/link is being setup either in some menu plugin (e.g. A&M Nav) or in your Twig templates (in your master/layout template or some included template specific to the menu or nav).


Ok, update..

The problem of my high memory usage was caused by (I think the logging of) devmode.. When I set devmode to false the moment that hit 10+gig memory before now has 100mb of memory usage...

Resetting memory on the different tasks that get initiated in the same function or as subtasks is not possible I guess?


Checking if matrix lightswitch is true, and add wrapper div

Judging from your code it looks like you are struggling with one of Matrix's limitations. Nesting. I have seen, and used, a number of hacks to get around this until I stumbled upon the Neo plugin. I, in fact, use it exclusively for this kind of thing; Bootstrap's and Foundation's rows and columns.... or any other flex grid system for that matter.

So this answer's kinda a non answer because I am going to point you in another direction to achieve Foundations Block Grid.

Because Neo can nest and the code is very similar to a structure using levels, you can do something like this for Foundation's Block Grid.

{% for row in entry.neoField.level(1) %}

  {% for column in row.children %}
    {% if loop.first %}
{% endif %}

            {% for field in column.children %}
            stuff... (use your switch code or I prefer per-field includes)
            {% endfor %}

    {% if loop.last %}
{% endif %}
 {% endfor %}

{% endfor %}

Will output

So in Neo I have a top level block called "Row". It has no fields, but it could, you can make it as complicated as you want adding class, background etc. This row block can only have one type of child block called "Column" again, no fields if you don't want. This "Column" block can have any number of child blocks including photo, text, video(even a Row! Inception!). For each row you add, you can have as many columns you want(zurb block grid only works to 8). The total amount of columns you add gets added to the medium-up-3 per the {{ loop.total }}.

Neo Field

Note: The code above is a simplified version. Doing the Row > Column > Row works, but the code's a little more complicated.


Twig Error Runtime When Using Conditionals

Craft doesn't redirect to 404 if a page isn't found, it just loads the 404 template and keeps the invalid uri.

What currently happens:

example.com/invalid_uri
Craft doesn't find it and shows the 404 template
Your conditional checks if 404 is in the uri, but it isn't.
Your code now tries to access the entry variable which isn't defined.
This results in a Twig error.

.

Solution:

Add an entry is defined to your conditional:

{% if craft.request.getSegment(1) != "404" and craft.request.getSegment(1) != "databytes" and entry is defined %}
....
{% endif %}


For anything else than base element fields, you'll need to use an inline fragment to fetch your custom fields like so:

query test {
  entries(section: "vacancies", limit: 20) {
    title
    expiryDate
    ...on sectionHandle_entryTypeHandle_Entry {
      description
    }
  }
}

Replace sectionHandle and entryTypeHandle with your values, I guess something like vacancies_vacancies_Entry


Is it possible to output the name of a Matrix Block?

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

{{ block.type.handle }}


Well, if you submit to your add to cart form via ajax, you will already get a json response - with an error - you can simply grab that error, test for Not a purchasable ID and then change the text to whatever you want.

If you're submitting in a non ajax fashion, you won't get a JSON response no matter what clearly.

I agree with the comment above - I'd generally handle this in front end JS, by disabling the add to cart until a size is selected.  And I guess if you're allowing your site to use no-js, then in that case I would probably just pre-select the most popular option (Medium, presumably).

You can also write a plugin that listens to https://craftcommerce.com/docs/events-reference#commerce_cart.onbeforeaddtocart and does whatever validation you need, and returns a response any way you want, including via JSON (i.e. $this->returnJson(["success"=>true]); or e.g. $this->returnErrorJson($errors); where $errors holds your validation errors...)


Restricting access to fields based on user group

You can use the Control Panel User Group plugin to automatically add special classes to the <body> tag in the CP.

Once those classes are in place, it's easy to use CSS or JavaScript to hide fields from certain user groups (or trigger other behavior based on user group status).

* Disclaimer: I'm the author of all of those plugins. :)


How to programmatically set a Smart Map address field in plugin

I figured it out, didn't realise all I had to do was pass array like so:

$entry->getContent()->address = array('lat' => $lat, 'lng' => $lng, 'street1' => $street1, 'zip' => $postcode);


Trigger off canvas menu upon adding product to cart

The basic recipe is this, and you can definitely do it without a page reload:

In your JS, listen for the form's submit event
Prevent the default submit
Ajax submit the form's data to the Commerce addToCart controller
Grab the result of this call...
If error - show error
If cart - JS pass the cart's data off to your drawer system and print out the cart that way (that's the quickest way, or you can just ajax load in a Craft template to where you have your drawer, the cart variable in that will have the updated cart data)


You can get the current locale’s name via craft.i18n.getCurrentLocale().

{% set locale = craft.i18n.getCurrentLocale() %}
{{ locale.name }}

That will output the name using the current locale’s translation.

If you would prefer to output the locale’s name in its native tongue, use nativeName instead:

{{ locale.nativeName }}

You can also output the name of any locale using (not necessarily the current one) using craft.i18n.getLocaleById():

{% set locale = craft.i18n.getLocaleById(entry.locale) %}
{{ locale.name }}
{{ locale.nativeName }}


I think you'll need to implement this with the Elements::EVENT_AFTER_SAVE_ELEMENT event and keep a record of the number.
If it doesn't need to be sequential 1,2,3 you could use a dynamic title and use {{object.sourceId}} which would be the entry id which will always increment


No input file specified - [proxy_fcgi:error] Got error 'Unable to open primary script: [PATH]/html/index.php (No such file or directory)\n'

It turned out that the problem was from customizing the domain's document root in the userdata files and then the PHP-FPM configuration had not been rebuilt and the service not restarted.  The following resolved the issue:

/scripts/php_fpm_config --rebuild
/scripts/restartsrv_apache_php_fpm

It's interesting since there are a broad variety of issue that seem to cause this No input file specified issue, but they all mostly revolve around Apache config issues.


ElementAPI: How to order and/or limit results?

Just setting the limit property doesn’t do the trick alone, you need to deactivate pagination, too:

'criteria' => [
    'section' => 'trucks',
    'limit'   => 10,
    'orderBy'   => 'title asc',
],
'paginate' => false,


Categories field is losing its value when programmatically updating other fields’ values

Update - Craft 3

This has been fixed. The relational field will retain its original value when an entry is re-saved.

You no longer need to apply a workaround to get the expected behavior.

Original - Craft 2

This is, admittedly, super awkward right now. To prevent a relational field from losing its value when saving an entry, you have to explicitly set its value to null:

$entry->setContentFromPost(array(
    'myCategoriesField' => null
    // ...
));

However, this only works for relational fields that aren’t set to Required. If the field is set to Required, you have to just re-set the field to the same element IDs that were already selected:

$entry->setContentFromPost(array(
    'myCategoriesField' => $entry->myCategoriesField->ids()
    // ...
));

(FWIW, this will stop being awkward in Craft 3, as we done some major refactoring under the hood to fix issues like this.)


Seems doable with a custom plugin.

The pseudo-code would be something like:

Use AssetsService to grab all of the files for the source.
Loop through the files and parse the parent folder paths.
Based on the subfolder for the asset, check if an existing tag already exists with the TagsService.
If 3 is true, assign that tag's value to a tag field on the Asset.
If 3 is false, create the tag using the TagsService, then assign that tag's value to a tag field on the Asset.


Is it possible to route to www.site.com/username?

I would not particularly advise creating a uri pattern that was just 'www.site.com/username' because usernames can essentially be anything which might cause routing conflicts (i.e. if the username is 'index' for example). You could however use something like 'www.site.com/members/username' or 'www.site.com/u/username'.

One way to do this would be to add a route using a 'subpattern'. For more info check out the routing docs on accessing subpatterns in your templates.

Here is the example given in the docs, which provides the variables 'year' and 'month' to the template that correspond to the matched uri segments (i.e.  `news/2015/02'):

'news/(?P<year>\d{4})/(?P<month>\d{2})' => 'news/_archive',

You could essentially do the same thing but with a 'username' variable.

'u/(?P<username>[^\/]+)' => '_thisTemplate',

You can then use the 'username' variable in your template to retrieve the corresponding user.

{% set user = craft.users.username(username).first() %}
{% if user %}
    {{ user.firstName }}
    ...
{% else %}
    {% redirect 404 %}
{% endif %}


To my knowledge this is not possible natively in Twig. Depending on your situation / template needs here are some useful tests

{% if foo is iterable %}

Array or object

{% if foo is same as(true) %}

Basically identical to using === in php


Default to only showing 'Live' entries in CP?

I'm adding Brad's comment here as an answer as I think it addressed indirectly this issue:

Craft 2.3 should fix the performance problem of Structures and Categories with large amounts of entries.


How to access a digital products information on the products page in Craft Commerce?

Instead of entry use product variable. For example, {{product.title}}.


Correct way to set up development and production environments for Craft?

I'd recommend you take a look at the excellent existing threads on this:

Git Workflow and Multi Environment - how to approach
What's the best practice for handling data migration and organization across development environments?

as well as the official documentation on Multi-Environment Configs


How do I add more account fields for user registration?

Create the input fields as you would any other, maybe add them to a 'users' group, then you can go to:

/admin/settings/users/fields

and add them via the layout designer, you should then see them appear when viewing a user in the admin area, under the profile tab I believe :)


Get the author of current entry version?

You have to write a template variable that makes getVersionsByEntryId() available in Twig.

public function getVersionsByEntryId($entryId, $localeId, $limit = 1, $includeCurrent = true)
{
    return craft()->entryRevisions->getVersionsByEntryId($entryId, $localeId, $limit, $includeCurrent);
}

You can now access an entry’s versions and get the current version’s creator like so.

{% set versions = craft.businessLogic.getVersionsByEntryId(entry.id, entry.locale) %}
{% set author = versions|length ? versions[0].creator : entry.author %}

{{ author.fullName }}


Possible to merge and sum the values of an array?

What you need to do is to add the row.points to any existing points for each type, before merging – otherwise you'll just overwrite the existing type/attribute and its values (in other words, the |merge filter won't automatically merge number values inside an object).

Something like this should work – note the use of the |default filter, to fall back to 0 if the results[type] key doesn't exist:

{% set results = {} %}

{% for row in entry.surveyData %}
    {% set type = row.contentType %}
    {% set pts = row.points + results[type].points|default(0) %}
    {% set results = results|merge({ (type) : {'name': type, 'points': pts } }) %}
{% endfor %}


You can access each adjuster and its respective amount via the cart.adjustments tag. Here's the example supplied with the templates from the commerce plugin (commerce/cart.html):

{% for adjustment in cart.adjustments %}

        {{ adjustment.type }}

        {{ adjustment.name }}
({{ adjustment.description }})
        {{ adjustment.amount|currency(cart.currency) }}

{% endfor %}

If you have set the included attribute of your Adjuster to true then it won't show up as an adjuster but only affect the cart amounts outputted (such as baseShippingCost and baseDiscount) so if you have something similar to the above already, that's why it won't be displayed. You can read more about the included attribute here.


Paginate entries ordered by a custom date field

Pulling it all inside paginate fixed it:

{% paginate craft.entries().section('events').limit(2).order('startDate asc') as events %}

{% for event in events %}
    // Event content
{% endfor %}

{% if paginate.prevUrl %}Previous Page{% endif %}
{% if paginate.nextUrl %}Next Page{% endif %}


How to slightly alter _layout for one specific page?

Try putting it inside of a simple block as the default value...

{% block contactButton %}
    {% include '_contact-button' %}
{% endblock %}

Then on your one-off page, override that block with emptiness...

{% block contactButton '' %}

Untested, but that should do the trick!


Translate field name displayed within validation error messages?

Craft/Yii sees that string as:

'{attribute} cannot be blank.' => '{attribute} darf nicht leer sein.',

Where {attribute} is the dynamic part - in this case your field handle.

If I'm understanding your question correctly, there isn't a way to translate that field handle in this context because you're in charge of what it's called to begin with.

I would assume, for example, if you're using the German locale, that you would already have a German context field handle name in place already.


Get the territory / country belonging to a locale?

You can't get a territory name directly from a locale tag (e.g. 'en' or 'en_gb'). But what you could do is to
take the territory part of the tag (two letter country code; keep in mind, it's optional) and get the territory
name via getTerritory:

{% set locales = ['en_gb', 'fr_fr', 'zh_cn'] %}

{% for locale in locales %}

    {% set subTags = locale|split('_') %}

    {% set territory = subTags|length > 1 ? craft.i18n.getLocaleData(craft.locale).getTerritory(subTags|last) : '' %}

    {% set language = craft.i18n.getLocaleById(locale).name %}
    {% set language = language ?: craft.i18n.getLocaleById(subTags|first).name %}
    {% set language = language|replace("/- #{territory}$/", '') %}

    {% if territory and language %}

Territory: {{ territory }}, Language: {{ language }}

    {% endif %}

{% endfor %}


Manually passing page number to paginate tag

If you're looking to display a set of Elements that simulate a paginated query, you might actually be looking for the offset Query parameter.

Here's an example of fetching a “page” of results based on a number of entriesPerPage and the number of pagesToSkip:

{% set customPageOfEntries = craft.entries()
    .offset(entriesPerPage * pagesToSkip)
    .limit(entriesPerPage)
    .all() %}

Of course, this doesn't include the ability to see how many pages of results you have, or to generate links to other pages of results.


How do I assign a language to all datetime outputs

Thanks to Kelsey Martens of solspace I found the key. The solspace demo calender uses the .format() method which doesn't translate to the sites language. Now I use the |date filter instead which translates also month and daynames.


On the server, check:

if the folder exists?
Check the folder permissions are set to 777 (could probably reduce to 755)

Within Craft:

In: Settings > Assets > Asset Sources - make sure File System Path and URL fields, have no leading forward slashes e.g.

imgs/logos/


Does Craft support a custom authentication backend for Admin?

Is there any way to implement this sort of SSO in a modular fashion in Craft?

Yes.

I'm not aware of any LDAP plugin for Craft, yet, but OAuth has already been done (https://dukt.net/craft/oauth).

See here for a bit on how you'd approach it.


Why Does Manual Cache Clear Work But CP Task Fails?

It's a fairly common problem: https://craftcms.com/guides/resolving-stalled-background-tasks


Verify if unrelated items are in the cart

In essence, if I am reading that right, can you reverse the question?  I.e. it seems that what you want to know is, for each accessory in the cart, is there a reverse relation back to at least one product in the cart.

This is definitely possible - you can read about reverse relations here: https://straightupcraft.com/articles/introduction-to-relations-and-reverse-relations-in-craft-cms-with-examples and of course at https://craftcms.com/docs/relations

..basically just loop through each accessory and check the |length of the result of a relatedTo that specifies what you want it to be related to (.e.g a product category).


valet share, ngrok giving 404, CORS errors

I'm not 100% sure this is the answer to your issue; but this might be the solution:

Helge has written an article here about using ngrok with Craft CMS (which I'd recommend looking over if you haven't already). In particular, he mentions he has the following lines in his Craft config particularly for logging into the CP over ngrok:

// Logging in to the CP will fail unless you turn off CSRF protection.
'enableCsrfProtection' => false,

Try that config option and see if that fixes the issue for you...


Sharing a template with identical category and tag name

If the url for posts with the category design is .com/news/design and the url for posts with the tag design is also .com/news/design, then you are not going to be able to see both lists. You do need that extra segment in the url.

What I do to stay DRY is let Craft route tags and categories to different templates (so you don't have to repeat the is this a category or a tag logic). Then on the different templates, use a macro or include for the common code.

Here is what the categories page looks like with a macro:

{% extends '_layout' %}
{% import '_macros/_news' as news %}

{% set newsPosts = craft.entries.section('news')relatedTo(category).limit(5) %}

{% block content %}

Entries with category {{category.title}}

  {{ news.index(newsPosts) }} {# all the shared code is in news.index() #}
{% endblock content %}


How to use sprite sheets effectively and responsively in Craft

I thought I'd just add my two cents, since no one has answered this yet. :)

It's not clear from your question if these image elements are purely front-end design assets, or if the client/end-user needs to update them from within Craft.

In the case of front-end assets, my opinion is that how these are used in your site is part of the projects build phase, and not something Craft should be responsible for. If Craft starts implementing support for generating sprite sheets, there're tons of other front-end stuff that would be just as relevant to add. Compiling SCSS/LESS/Stylus, concatenation and minification of CSS and JS, building web fonts from SVG files, minification of images and SVGs, etc. I don't feel that this is what P&T should spend their valuable time on. :)

There are numerous ways to automate building a sprite sheet as part of the build, I use grunt-spritesmith which also gives me a complete stylesheet with classes for all the different elements.

If the problem is that the client needs to update the assets, I see why the sprite sheet has to be generated by Craft. It would be possible to make a plugin that creates a stylesheet from all images in a folder, a list of images or something like that. It would probably involve a lot of inline css, since you wouldn't know the sizes and positions of the different elements in advance.

But, depending on the nature of the elements I'm not sure if I think it's worth it.  Since you're considering making a sprite sheet I guess that the elements isn't actual content (ie images that should be accessible, searchable by Google, etc)? In that case I think I'd just lazyload them if they result in too many requests. If the elements is actual content, combining them into a single image would really ruin accessibility, so that is a really bad idea anyhow.


In theory, all plugins should be 5.3 compatible... but of course, it's up to the plugin developer to decide their own minimum requirements. 99% of publicly available plugins seem to be 5.3 compatible.

The biggest "gotcha" between 5.3 and 5.4 is the simplified array notation. In 5.4, you can declare arrays with simple square brackets ([]), instead of the more verbose array() syntax. That's one of the most notable changes between versions. Although, this doesn't seem to be the problem you're having. You'd at least see the plugin load, and kick up some sort of error message.

I'm guessing that you're testing the 5.3 vs 5.4 requirements on two separate servers? If so, you're probably running into an uppercase/lowercase problem. This actually has nothing to do with the version of PHP... Some servers care about casing, while others don't.

See this thread for a full explanation on casing, and why it might be causing your problem:

  https://craftcms.stackexchange.com/a/1537/45


Have staging or dev in the name, as in blah.dev.domain.com or blah.staging.domain.com  It needs to be a full sub-domain, not a partial like you had in your example.


Put simple content into Craft and grab it in JavaScript

One way to go about this is to use the JSON Expand plugin from Familiar Studio:

https://github.com/familiar-studio/craft-json-expand

It's pretty easy to use:

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

Then you can just grab the data you need from the json object like:

<script type="text/javascript">
    var homepageContent = hpContent|json_expand|raw }};
    console.log({{ hpContent|json_expand|raw }});
</script>

One caveat I've found though is that content in Rich Text editors doesn't output.  If you're just using simple text fields, then you should be fine.  If you do need something Rich Text-like, you could use Craft's |markdown filter on data from a simple text field.


Check for whole cart adjustment and apply line item discount

Success!

1) I have an Event that does a EVENT_BEFORE_SAVE_ELEMENT check.

Event::on(Elements::class, Elements::EVENT_BEFORE_SAVE_ELEMENT, function(Event $event){

    /**
     *  Runs so an admin doesn't have to set SKU or Slug when creating a NEW SONG
     *  This Event will also set the Price based on the Price Group Category Selected
     */

    // Only perform action if we are working with a Digital Product and Song Type
    if ( ($event->element instanceof \craft\digitalproducts\elements\Product) && ($event->element->typeId == 1) ) {

        // Only adjust the SKU and Slug if this is a NEW Digital Product
        if ($event->isNew) {

            // Get the last row from the Content Table
            $lastId = (new \craft\db\Query())
                ->select([
                    'elements.id'
                ])
                ->from('elements')
                ->orderBy('id DESC')
                ->limit(1)
                ->one();

            // Increment the Last ID number by One. This will work fine unless the last item was deleted.
            // But the point of this is to assign a new, unused number to the Slug and SKU anyway
            $songId = $lastId['id'] + 1;

            // Assign the SKU and Slug
            $event->element->sku = 'song-' . $songId;
            $event->element->slug = $songId;
        }

        // Get the price from the Price Category
        $categories = $event->element->getfieldValue('priceCategory')->one();
        $productPrice = $categories['productPrice'];

        $event->element->price = $productPrice;
    }
});

I also have a method that checks the Categories. If the price changes there, then it goes back and updates the prices on all the products, too.

2) Then, to connect the Verbb Gift Voucher plugin and to adjust the Line Items by a percent discount, I run this EVENT_REGISTER_ORDER_ADJUSTERS

Event::on(OrderAdjustments::class, OrderAdjustments::EVENT_REGISTER_ORDER_ADJUSTERS, function(RegisterComponentTypesEvent $event) {
    $event->types[] = CartAdjustmentsAdjuster::class;
});

which is this:
    class CartAdjustmentsAdjuster implements AdjusterInterface
    {

    // Properties
    // =========================================================================

    private $_orderLineItems;

    // Public Methods
    // =========================================================================

    public function adjust(Order $order): array
    {
        $adjustments = [];

        $this->_orderLineItems = $order->getLineItems();

        // Get the Voucher code by session
        $giftVoucherCodes = Craft::$app->getSession()->get('giftVoucher.giftVoucherCodes');

        if (!$giftVoucherCodes || count($giftVoucherCodes) == 0) {
            return [];
        }

        foreach ($giftVoucherCodes as $giftVoucherCode) {
            $voucherCode = Code::find()
                ->where(['=', 'codeKey', $giftVoucherCode])
                ->one();

            if ($voucherCode) {

                $priceAdjust = (new \craft\db\Query())
                    ->select([
                        'content.field_prePayDiscount'
                    ])
                    ->from('content')
                    ->innerJoin('giftvoucher_codes', '[[giftvoucher_codes.voucherId]] = [[content.elementId]]')
                    ->where(['=', 'giftvoucher_codes.codeKey', $voucherCode])
                    ->all();

                $discount = $priceAdjust[0]['field_prePayDiscount'];
                if($discount > 0) {

                    foreach ($this->_orderLineItems as $item)
                    {
                        $origAmt = $item->price;
                        $saleAmt = ($discount / 100);
                        $discountAmt = $saleAmt * $origAmt;
                        $discountPrice = $origAmt - $discountAmt;

                        $item->saleAmount = $saleAmt;
                        $item->salePrice = $discountPrice;
                    }
                }
            }
        }

        return $adjustments;
    }
}

One important note is that this custom adjuster needs to be installed first before the Verbb Gift Voucher plugin so that the Gift Voucher amount will be applied after the Line Item adjustments are made.

The docs state:

  You could have a project level event listener, that could reorder these adjusters, and not append any new ones.

But installing in this order works, too.


Retrieving an entry based on the request URI in a plugin controller

You can grab the current entry using the $uri = craft()->request->getRequestUri() which will return the URI in a format like so:

/path/to/uri

To grab the entry, its easiest to grab the element first, based on the URI, using craft()->elements->getElementByUri($uri). However, this will not work because of the beginning slash that is returned by getRequestUri. So you must remove the slash using ltrim like so:

$uri = ltrim(craft()->request->getRequestUri(), '/')

Once you have the URI, minus the beginning slash (path/to/uri), you can use $element = craft()->elements->getElementByUri($uri) to return the element and then grab the entry using $entry = craft()->entries->getEntryById($element->id).

If you were going to need this often, you can place it in a helper method on the controller.

private function getEntryByRequestUri()
{
    // remove the first trailing slash
    $uri = ltrim(craft()->request->getRequestUri(), '/');
    $element = craft()->elements->getElementByUri($uri);
    $entry = craft()->entries->getEntryById($element->id);
    if ($entry == null) {
        // log something and do something
    }
    return $entry;
}


How do I set Redactor formatting button to wrap selected text in two tags? ...

If it were me, I'd try to keep as much formatting cruft out of a wysiwyg as possible, it cleans things up down the road and keeps your content as structured as possible. If you ever change frameworks or anything else, that extra cruft can come back to haunt you because it's all stored in the database.

A better way is handle this with a couple Matrix blocks. Set one up for text, and then another one for code snippets. Then in your template when you want to spit out a code snippet, you just wrap it using whatever extra bits you need like:

{% for block in entry.myMatrixField %}

{% if block.type == "text" %}
    {# handle text #}
    {{ block.entryText }}

{% elseif block.type == "code" %}

{{ block.codeBlock }}

    </div.

{% endif %}

{% endfor %}

The upside here is that it's all built-in, you don't have to modify any redactor defaults to make this work. But the bigger upside is if let's say you're building a library of code snippets, it'd be super easy to query the Matrix fields and get just those snippets you want.

You could even completely reformat the page and just show the code snippets, since you have them already broken out.

IMO that's what makes Craft so powerful, it's easy to use more structured data unlike other solutions *cough* like WordPress *cough* that put everything in one "field."


Include single entry type with custom parameters in the for loop within multiple entry types

One way to merge two distinct elementCriteriaModels is to perform each query separately grabbing their 'ids', then merge the 'ids', and perform a new query using the 'ids' as the only parameter.

{% set first10 = craft.entries.type('entryTypeHandle').limit(10).ids() %}
{% set all = craft.entries.ids() %}
{% set first10-All = all|without(first10) %}
{% set entryIds = craft.entries.limit(10).id(first10-All).ids() %}
{% set specialIds = craft.entries.type('entryTypeHandle').offset(10).ids() %}
{% set entryIDs = entryIds|merge(specialIds) %}

{% set entries = craft.entries.id(entryIds) %}
{% paginate entries as entriesOnPage %}
    {% for entry in entriesOnPage %}
        {# entry #}
    {% endfor %}
{% endpaginate %}

I also notice a few other issues in your example, that might be causing you some problems.

I see a lot of empty query parameters which are not needed — keep in mind that empty parameters will not really affect the results. (i.e. craft.entries.section().types() is really the same as just craft.entries, which, in this case, will return all entries).
By modifying an existing query, you are essentially creating two queries to the database, which may not be what you're after.

{% set params = craft.entries.section().types() %}
{% set entries = params.limit(10) %}

This works, but you are essentially querying the database twice, creating two elementCriteriaModels. A better way to do this is to use a parameters array.

{% set params = {
   section: 'mySectionHandle'
} %}

If you later need to add more parameters, you can do so using the merge filter, before running the query. The result is that you will only be querying the database once.

{% set params = params|merge({ limit:10 }) %}
{% set entries = craft.entries(params) %}


It looks like setFormFieldValues() has an optional second parameter related to overriding values...
public function setFormFieldValues(array $values, bool $override = true)
So, changing...
$submission->setFormFieldValues(['customField' => $customFieldValue]);
... to...
$submission->setFormFieldValues(['customField' => $customFieldValue], false);
may help with the override issue.


These are the settings I have in place for config.php and .htaccess file.


A rather sneaky solution to your issue could be to create a matrix field that has one block type per category group. Each of those block types then could contain a single category field with the category source set to the corresponding category group. Limit those category fields to 1 category each and then limit the matrix field to one matrix block.

This way your editors will be able to select only one of the matrix block types and that block type will limit the categories to the selected group.

If you need this for some custom markup wizardry in your templates, make sure you understand variable scoping in Twig loops if you're trying to set some variable value while looping through your matrix data.


Deleted rows from elements_sites hunting stray slugs now I can't login

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

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

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

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

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

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

}

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


You can’t set the craft.locale from the template. You can set the locale for your Element Criteria though.

{% set entry = craft.entries.id(14).locale('en').first() %}


I would use the group filter:

{% for author, entries in craft.entries.find() | group('author') %}
    {{ author }}

        {% for entry in entries %}

{{ entry.title }}

        {% endfor %}

{% endfor %}


I don't think you can cache that, since the tag is run server-side and rendered with template output, and will be unique on every page load. If you have content that's unique on every page load, you'd have to either ignore that page from CDN caching, or dynamically load in the unique content after page load via an AJAX call to a page that is ignored from CDN caching.


What is the Pricing Structure for CraftCMS?

One license per site, not a renewal (one time purchase)


How to set different file size upload limits for different Asset Sources

Craft has no settings defined for it. The only setting it has is maxUploadFileSize which you have already mentioned. So the solution of this is using Imager Plugin. There is also a blog from nystudio107 on this. Let Client upload image of any size or dimension, but you could resize them using Imager plugin.


Im my form, I also have a hidden field for the user photo:

<input type="hidden" name="photo" value="{{ currentUser.photo }}">.

I have {% if currentUser.photo %} instead of {% if currentUser.photoUrl|length %}.

Also,  instead of . This should display the current photo.

EDIT:

File input field name should be photo: <input type="file" id="photo" name="photo">


Type number form in textField for plugin

Not tested yet.

{{ forms.textField({
        label: 'Number Field',
        id: 'someId',
        name: 'someName',
        value: '',
        min: 0,
        max: 100,
        size: 1,
        type: 'number',
        value: settings['someName']
    })
    }}

I think you can use min and max


Show 2 random entries based on checkbox in Super Table

The question is pretty confusing so this answer assumes the following:

You have a Super Table field named entryType with the following cells:

featuredIn (checkbox)
showInRandom (checkbox)

And that you are trying to:

Only show rows where showInRandom is checked
Randomize the order of the rows that are returned
Limit the returned results to 2

Unfortunately Super Table doesn't support searching based on a block's value, which I see you already know, so you'll have to do it in steps.

First, you need to pull in every Super Table row. Then you need to check if each row has showInRandom checked (side note: a lightswich field would be easier), and add its ID to an array if so. Then you randomize the array and run a Super Table query with those IDs and limit the results to 2.

{# create an array to store the returned IDs #}
{% set randomRows = [] %}

{# add only the rows with showInRandom selected to the array #}
{% for row in entry.entryType.all %}
    {% if row.showInRandom.options[0].selected %}
        {% set randomRows = randomRows|merge([row.id]) %}
    {% endif %}
{% endfor %}

{# randomize the array and run a super table query, limiting to 2 #}
{% for row in craft.superTable.blocks({
    owner: entry,
    fieldId: 123,
    id: shuffle(randomRows),
    fixedOrder: true,
    limit: 2
}).all %}
    {{ row.someField }}<br>
{% endfor %}


Using relatedTo, and/or and :empty/:notempty in queries

Please don't laugh, but I thought to myself, let's give this a go in Twig and see where it takes me.
It very soon began to become clear, that this will end up in lots of criteria models, db queries and a huge pile of Twig code.

So my better answer should be, don't do it in Twig. This is something you should better do in PHP with
custom database queries (→ Yii query builder). But now that I've done it, here's a gist of that Twig code.


Where should I add the file to write the code for the `afterSend` event for contact form plugin?

You should add it to custom-made module.

Go to https://pluginfactory.io/ to generate your module scaffolding (you don't need to select any additional components like models, variables etc for this), then install it accoding to instructions in readme file.

After that, attach to event in module init() function:

    public function init()
    {
        parent::init();
        self::$instance = $this;
        Event::on(Mailer::class, Mailer::EVENT_AFTER_SEND, function(SendEvent $e) {
           // custom logic...
        });
    }


Specify a specific entry type in paramaters

I suspect the only way to do this at the moment would be to look up the EntryTypes for each of the desired Sections, and filter just by those—ignoring the section query facet. For example:
{# Map some Section handles into actual Section models, using the Sections Service: #}
{% set sections = ['one', 'two', 'three'] | map((h) => craft.app.sections.getSectionByHandle(h) %}

{# List your "forbidden" Entry Types in a `sectionHandle:entryTypeHandle` format, so we can filter them out, in a moment: #}
{% set forbiddenEntryTypes = [
  'mySection:entryTypeOne',
  'mySection:entryTypeTwo'
] %}

{% set entryTypes = [] %}

{% for section in sections %}
  {# Get the section's EntryTypes, filtering out any that don't match our "magic" `section:entryType` values in the "forbidden" array, above: #}
  {% set permittedSectionEntryTypes = section.getEntryTypes() | filter((t) => "#{section.handle}:#{t.handle}" not in forbiddenEntryTypes) %}

  {# Merge anything that passes the test into the main `entryTypes` array: #}
  {% set entryTypes = entryTypes | merge(permittedSectionEntryTypes) %}
{% endfor %}

{% set query = craft.entries({
  type: entryTypes
}) %}

This basically works by assuming you want all types from all sections, then filtering out just a few types from that list.
For example, your forbiddenEntryTypes might look something like this, if you had three other Entry Types in the Courses section…
{% set forbiddenEntryTypes = [
  'courses:night',
  'courses:takeHome'
] %}

…where cce is allowed, because it's returned by the section, but not explicitly filtered out. You'll have to update this if/when you add more Course types!

Keep in mind that the sectionHandle:entryTypeHandle format is not a Craft feature, it's just a way for us to compare Section + Entry Type handles at once (note the way we build the "#{section.handle}:#{t.handle}" string when filtering down the Entry types)!


Error with Craft CMS set up and composer: failed: SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: YES)

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

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

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


Adding an event handler is not something you do through the control panel.

What you need to do is create a plugin (pluginfactory.io makes this fairly easy), and in your plugin's main class, you have an init() function that looks like this:

public function init()
{
    craft()->on('sproutForms.onSaveEntry', function (Event $event) {
        $entry = $event->params['entry']; // fetch the new entry
        ... do things with $entry ...
    });
}

If you structure your plugin properly, you will "do things with $entry" by calling a Service.


Exclude a block from appearing on a specific page

You can check against the Entry Type as well.
I would try to validate it with something like:

{% set exclusions = ['home'] %}
{% if entry.type not in exclusions %}
....


Commerce does not have a back-ordering (negative stock) counter at the moment. To allow ordering of more items that you have on hand, you would need to either:

1) enable the 'unlimited stock' option on the variant which would not track the stock and allow orders of an unlimited number of variants.

2) Choose an arbitrarily high stock count to allow ordering above what you have on hand. For example, if you have 32 items on hand, make the stock value 2032, allowing for the stock to drop below 2000 would let you know the number of back-orders.

Either of these might not be ideal.

A third option could be using option 1 with a plugin that listens to the onOrderVariant event and updating your own stock counter within your own database tables.

We hope to have features like back-ordering in future versions of Craft Commerce, and you can vote for such features here: https://craftcms.uservoice.com/forums/295386-commerce/suggestions/7817436-pos-and-inventory-management

Hope that helps.