Find specific image from global image set?

When you call myGlobalSet.myAssetsField, you're creating an ElementCriteriaModel. This is significant, because an ElementCriteriaModel is basically a "search object".

Your design.imgs call produces an ElementCriteriaModel based on craft.assets. It will return only the assets which are related to your global field.

You can manipulate your ElementCriteriaModel in whatever way you want!

{% set myAsset = design.imgs.kind('image').sourceId(1).first %}


EVENT_AFTER_SAVE_ELEMENT triggered twice after saving an entry

You can find out what the stack trace is (who is calling you) by putting something like this in your anonymous function:

                try {
                    throw new \Exception();
                } catch (\Exception $e) {
                    Craft::debug(
                        'EVENT_AFTER_SAVE_ELEMENT '.$e->getTraceAsString(),
                        __METHOD__
                    );
                }

Then search on EVENT_AFTER_SAVE_ELEMENT in your web.log


Utilizing/ Converting another database with craft

Welcome to Craft! Craft does not require coding experience to set up fields and relationships (attendees to events, for example). All of that is handled from the control panel.

Displaying the fields on the frontend requires some knowledge of Twig, the templating engine Craft uses.

Transferring the data may require some pretty heavy coding, depending on how the data is currently structured. There are a few importing plugins (here's a popular one) that might be able to help. From your numbers above, migrating by hand may not be an option, so you might need to invest in some research or hire a developer to help with that phase.

Craft has a lot to offer out of the box in terms of organizing content. I could see you making use out of singles and structures to manage events, hotels, attendees, etc. I recommend reading through the introduction documentation to get a hold on how Craft is set up.


It was a problem on our side but we just pushed a fix. If you try again, you should be able to get on now.


Programmatically create a product using Craft Commerce 2?

You probably have it figured by now, but for anyone wondering, here's a complete working example.

use craft\commerce\elements\Product;
use craft\commerce\elements\Variant;

// Create product
$product = new Product();
$product->title = 'Hello world';
$product->typeId = 2;
$product->enabled = true;

// Create variant
$variant = new Variant();
$variant->title = 'hey';
$variant->sku = 'hey';
$variant->price = 123;
$variant->stock = 5;

// Save product with variant
$product->setVariants([$variant]);
Craft::$app->elements->saveElement($product);


Element API: Get Entries Related to Category with Query Parameter

Are you passing the projectCategory parameter as a string or ID? In any case, the relatedTo parameter will receive a string in your code, which might trip up the query. If the parameter is passed as an ID, passing it as an integer instead of a string might be enough:
'relatedTo' => (int) $projectCategory,

However, it might be cleaner to get the actual category element based on the ID and pass that to relatedTo. This will also allow you to check if the specified category actually exists (and optionally return an HTTP error for invalid parameters).
$criteria = ['section' => 'projects'];
$projectCategory = \Craft::$app->request->getQueryParam('projectCategory');
// this assumes the category is passed as an ID
$category = \craft\elements\Category::find()->id((int) $projectCategory)->one();
if ($category) {
    $criteria['relatedTo'] = $category;
}


Craft only ships with a subset of Yii’s supported locales, to cut down on the filesize. It’s easy to add additional ones though. Instructions are here: http://buildwithcraft.com/help/adding-additional-locales


Keep on getting logged out when deploying using Capistano

The problem is that the basepath changes each time you deploy (Capistrano uses versioned release directories). The basepath is used to generate a session key, which is invalidated each time a new deployment is made.

The answer is to add the appId parameter to config/general.php. The docs give a good explanation

  The application ID, which is used for things like storing data caches and user sessions. If it’s not set, Craft will automatically generate one based on the server path. Setting it will help avoid the loss of data caches and user sessions when Craft is deployed using a deployment script that will store Craft in an inconsistent location, such as Capistrano.

So add this to general.php:

'appId' => 'chooseyourownrandomstring',


Adding items to cart from related entry not working

Just quickly as I'm on my phone...The two main ways to debug this sort of thing in Commerce are:

Check what you are actually POSTing matches what you think you are posting (to check this I just use the browser dev tools)
Check the flash data (notice and error) for messages when the page reloads (or check the JSON response if ajaxing).

Usually you'll get a sensible message back, e.g. out of stock or similar.

I use this code to dump the flash data (I think only error and notice are used these days, the commerce flash dates back from before commerce was released but it can't hurt!):

{% if craft.config.devMode and (craft.session.hasFlash('commerce') or craft.session.hasFlash('notice') or craft.session.hasFlash('error')) %}

        {% set isErrors = true %}
        {% set commerceFlash = craft.session.getFlash('commerce')|join('|') %}
        {% set noticeFlash = craft.session.getFlash('notice')|join('|') %}
        {% set errorFlash = craft.session.getFlash('error')|join('|') %}

        Commerce: [{{  commerceFlash }}]
        Notice: [{{  noticeFlash }}]
        Error: [{{  errorFlash }}]

    {% endif %}


Have you been through Craft's testing documentation? https://craftcms.com/docs/3.x/testing/
There's a pretty good walkthrough of the necessary steps there to test plugins: https://craftcms.com/docs/3.x/testing/testing-craft/setup.html
Or if you like more real-world examples, Commerce's tests are a good place to start: https://github.com/craftcms/commerce/blob/develop/codeception.yml
From then, you'd trigger all unit tests from the root of your project like:
./vendor/bin/codecept run unit

Or every test in a single file with:
./vendor/bin/codecept run tests/unit/helpers/LocaleHelperTest.php

Or a specific test within a single file with:
./vendor/bin/codecept run tests/unit/helpers/LocaleHelperTest.php:testEmailGetOrderLanguage


Can a plugin manually raise another plugin's Event?

I've built a plugin which uses it's own events before, I guess the way to do it would be the same for separate plugins, however this is untested for your use case.

This should go in your plugin service

// Import the event from the other plugin
Craft::import('plugins.otherPluginHandle.events.OtherPluginEvent');

/Initialise the plugins event and pass whatever is required to it.
$event = new OtherPluginEvent($this, array('request' => $request));

// Raise it.
$this->raiseEvent('OtherPluginEvent', $event);

Again I haven't tried this from the context of calling another plugins event, but that is what I do from a plugins own event...


How, in a plugin, can I check that a User's "Favourite Entries" field contains a specific Entry?

You can avoid looping by getting an array of the IDs of the favourite entries, then check to see if the specific Entry ID is in the array.

$favouriteEntryIds = $user->favouriteEntriesField->ids();
if( in_array($searchingForThisEntryId, $favouriteEntryIds) ) {
    ... the Entry has already been favourited ...
}


`onBeforeSaveUser` - Access existing user data

Not totally sure, but I believe this may be because the UsersService actually caches UserModels fetched by getUserById() locally in a private class variable.

Instead of using getUserById(), try pulling the user with an ElementCriteriaModel:

$existing = craft()->elements->getCriteria(ElementType::User, array(
    'id' => $userId,
))->first();


How to update Craft CMS/plugins without downtime?

I think the best solution would be to integrate a CI with "Zero downtime deployment".

You may have a look at this article:
https://craftquest.io/articles/what-are-zero-downtime-atomic-deployments

Or have a look at this deploy plugin:
https://github.com/elfacht/craft-deploy

Or just google for "zero downtime deployment".


Modifying the search order “Score” criteria

There currently isn't a native way to do this, and I'm not sure it'd be that easy for a plugin to easily pull off either, since there currently aren't any search related events exposed in Craft.

Probably worth adding a feature request for, though!


Filtering on related entries (with an array query param)

This should take care of it:

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

{# check if stage is an array #}
{% if stage is iterable %}

    {% for stageItem in stage %}

        {# make sure stageItem has content #}
        {% if stageItem is not empty %}

            {{ stageItem }}
            {# would output the selected stage.value #}

        {% endif %}

    {% endfor %}

{% endif %}


Localization - How do we manage multilingual, multi-environment on multiple domains?

You have one Craft install and one DB. Do everything described in that article, just replace the subfolder paths with the different domains:

return array(
    // ...
    'siteUrl' => array(
        'en' => 'http://example.com/',
        'es' => 'http://example.es/',
    ),
);

Then all you have to do is to configure your webhost so that it routes those domains to different index.php files. It should contain the info about the locale and point to Craft folder:

// Path to your craft/ folder
$craftPath = '../../craft';

// Tell Craft to serve the Spanish site
define('CRAFT_LOCALE', 'es');


How do we create a pre-defined Asset upload field in a plugin that integrates with the native Craft Assets file manager?

I did this recently with my Ad Wizard plugin... There are several different parts which need to be brought together to make it work:

In your Record file, add this to defineRelations:

'asset' => array(static::BELONGS_TO, 'AssetFileRecord')

In your Model file, add this to defineAttributes:

'assetId' => AttributeType::Number

Whichever template is responsible for editing that data will need something like this:

        Image

        {% if assetsSourceExists %}
            {{ forms.elementSelect({
                elements: elements,
                id: 'assetId',
                name: 'assetId',
                elementType: elementType,
                criteria: {"kind":[],"localeEnabled":null,"locale":"en_us"},
                sourceElementId: assetId,
                jsClass: 'Craft.AssetSelectInput',
                addButtonLabel: 'Select Image',
                limit: 1,
            }) }}
        {% else %}

No assets sources currently exist. Create one now...

        {% endif %}

You'll notice in the Twig code above, I set references to the following variables:

assetId
elements
elementType
assetsSourceExists
newAssetsSourceUrl

These variable were set in the actionEditMyElement method of the Controller prior to loading the template:

// Set assetId
$variables['assetId'] = $myModel->assetId;

// Set elements
if ($variables['assetId']) {
    $asset = craft()->elements->getElementById($variables['assetId']);
    $variables['elements'] = array($asset);
} else {
    $variables['elements'] = array();
}

// Set elementType
$variables['elementType'] = craft()->elements->getElementType(ElementType::Asset);

// Set assetsSourceExists
$sources = craft()->assets->findFolders();
$variables['assetsSourceExists'] = count($sources);

// Set newAssetsSourceUrl
$variables['newAssetsSourceUrl'] = UrlHelper::getUrl('settings/assets/sources/new');

// Render the template!
$this->renderTemplate('myplugin/_edit', $variables);

Your Controller will probably have something like this in your actionSaveMyElement method:

$myModel->assetId = craft()->request->getPost('assetId', $myModel->assetId);

Your Service file will probably have something like this to save your record:

$assetId = (!empty($myModel->assetId) ? $myModel->assetId[0] : null);
$myRecord->assetId = $assetId;
...
$myRecord->save();

Hope that helps, let me know if I missed anything!


No, "Default" is Craft's default configuration and is not user configurable.


Your customColor3a and customColor3b variables will always be defined so you need to check if empty.

{% if item.options.customColor3a is defined and item.options.customColor3a is not empty %} |
    Custom Color 1: {{ item.options.customColor3a }}
{% endif %}
{% if item.options.customColor3b is defined and item.options.customColor3b is not empty%} |
    Custom Color 2: {{ item.options.customColor3b }}
{% endif %}


Is it possible/recommended to use Solspace Freeform for a front-end user login form?

It’s potentially possible with a custom module, but it would be far less effort (not to mention, more secure) to just apply the solspace form classes to the regular log in form.


Craft not loading custom 404 template for errors

Turns out the general.php file had the following line (docs) in it:

'errorTemplatePrefix' => "_errors/"

Once I'd created the proper folder and files, all worked as expected.

Thanks, @CraftCMS Twitter person!


Is it safe to delete unused matrix field tables from the DB?

That shouldn't be the case... Those tables should have been deleted automatically when you deleted the fields.

Did you actually delete the fields themselves? Or did you simply remove them from your section's field layout? Make sure the actual fields were deleted within Settings > Fields

If you're positive those fields have been properly deleted...

Try updating to the latest version of Craft (v2.2.2587), which was released today. It includes this bug fix:

  Retroactively fixed a bug where some Matrix block rows would get left behind in the database when an element was deleted that had a Matrix field.

If that doesn't resolve the problem for you, I'd recommend submitting a bug report to Pixel & Tonic. Submit the message via your Dashboard, so you can include a copy of your database and log files.


Where to place a front-end 'entry form'?

You'd put it in your craft/templates folder at something like craft/templates/recipes/new.html.  Then you'd be able to load that from http://mysite.com/recipes/new.

There's a good templating overview in the docs here.


How to check for an non empty element field?

They'll all work except for the last one:

entry.fieldHandle.one()
entry.fieldHandle.all()
entry.fieldHandle.count()
entry.fieldHandle | length
entry.fieldHandle.exists()


populateModel usage with eager loading related records

Would like to know if this is the best solution? Upvote if you think it is.

The solution is make your own custom populateModel method to catch the eager loaded attributes

/**
 * @param array|Market_VariantRecord $values
 *
 * @return $this
 */
public static function populateModel($values)
{
    $model = parent::populateModel($values);
    if (is_object($values) && $values instanceof Market_ProductRecord) {
        $model->product = $values->product;
    }

    return $model;
}

I suppose the Craft core BaseModel could check if the value of type BaseRecord and do the same?


Losing focuspoint on saveEntry by plugin

I recently had the same problem when saving entries in my plugin. I only wanted to update an entry field that had nothing to do with the focus image and save that entry. Turned out the focus image lost its value (I think it happens only when the field is required).

I solved it by getting the value of the focusImageField and just re-set it when saving the entry:

$entry->setContentFromPost(array(
// imageWithFocusPoint is required but returns empty,
// so set it with same value it allready had
   'imageWithFocusPoint' => $entry->imageWithFocusPoint->ids(),
));

craft()->entries->saveEntry($entry);

More info that helped me here: http://goo.gl/soli9T

Another solution (and the one I used but maybe less of an option for you) is to disable validation on the entry save. By using:

craft()->content->saveContent($entry, false);

instead of saveEntry. The "false" as second parameter means it will not validate the entry which is not always necessary.


It works identically to entries.

Here are a couple things you can do to troubleshoot:

Make sure that user is set to the user account you’re expecting it is. You can double check that by outputting {{ user.username }}.
Make sure that you’re calling the right Matrix field handle, with the correct capitalization.
If you’re passing the type param, make sure you’re passing in the right Block Type handle.


Update a lightswitch field in Craft CMS 2

If it's only one single field and you want to bypass all Craft validations for required fields you can change the value directly in your database using Yii commands and the update function

function update($table, $columns, $conditions='', $params=array())

$command = craft()->db->createCommand();
$command->update('craft_content',
    array(
        'field_yourLightSwitchField' => 1,
    ),
    'elementId=:id', array(':id'=>1)
);

If you have a multilocale setup you need to include the condition for the correct locale as well


What would cause an Internal Server Error on saving entry

I have solved the problem myself while debugging.

I had the Entry Type "Title" field set to {relatedFieldName} Post which was causing the error. When I changed it to a plain string or other non-object field name, it no longer errors out.

I was unclear about how the Title field works exactly.


A conditional that keys off the presence of the second segment to determine what to show for the "Blog" link/copy will work.

{% set seg2 = "" %}
{% set seg2 = craft.request.getSegment(2) %}

Home

        {% if seg2 == "" %}
            Blog
        {% else %}
            Blog
        {% endif %}

    {% for crumb in entry.getAncestors() %}

{{ crumb.getLink() }}

    {% endfor %}

{{ entry.title() }}


Did you set up your Asset Volumes to have the proper paths/URLs? Do you have Assets in this volume have public URLs turned on?

Do you have a volumes.php configured to be multi-environment aware? It's not a necessary step, unless you require the now-deprecated environmentVariables settings:

https://docs.craftcms.com/v3/config/#aliases


Update existing entry from plugin not saving and producing no error

I haven't used getEntryById, and this isn't exactly an answer, but here is how I am doing pretty much the same thing:

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'mySection');
$criteria->status = null;
$criteria->limit = 1;
$entry = $criteria->first();

...
if ($entry) {
    $entry->setContentFromPost([
        'myFieldHandle' => 'woot'
    ]);

    craft()->entries->saveEntry($entry);
} else {
    // Could not find entry.
}

...

Unless you are setting the page title, then I think you need to use something like:

...
$entry->getContent()->title = 'woot';


Calling Craft Console Commands from Plugin?

Since Yii treats console commands like requests, you need to perform the following steps to execute a Craft console command from within a plugin:

Within your plugin, set the namespace to match the commands namespace
Call a run action from your plugin, and pass the route name/params

    MyPlugin::$plugin->getInstance()->controllerNamespace = 'craft\console\controllers';

    $command = MyPlugin::$plugin->getInstance()->runAction('gc/run');


Craft often requires a different approach than Wordpress, but can be just as easy and powerful to use when set up correctly. The big unknown in your situation is how your content architecture and templates are set up.

Content architecture and template decisions in Craft are custom from site to site and designed by the firm that created or maintains the website. To help further with you question, we'd need to understand how your sections and navigation are set up, if your sections have URLs, what assumptions your templates are designed to make about the content they output, and so on. Getting training from the firm who built the site or hiring a consultant to walk you through your site and give you a tour of how things work could be helpful in your situation.

A few resources that could help you get started:

Craft Feature Videos - Short videos on how key features in Craft work
Straight Up Craft Training - Free, weekly intro training
Mijingo Video Course - Overview of building a site in Craft

If you are in the situation where you are looking for a consultant or firm to work with, there are a couple of Craft professional listings and job directories. At the time of this post:

Straight Up Craft - Jobs
Straight Up Craft - Professionals
Work With Craft
Work With Craft - Professionals
Craft CMS Partners
Craft Slack #jobs channel


Craft 3 uses snake-case paths instead of camelCase paths
Your action parameter must be entries/save-entry

Its all stated in the docs

Edit: generally a good idea is to inspect the html in your cp form and copy it to your frontend. You'll be able to solve 90% of your issues that way


Why am I unable to use Twig conditional on entry.type property?

Your problem is that entry.type is actually not a string, but an instance of EntryTypeModel. This means that entry.type is an object containing many different properties, among them the handle, which would be the property that you want to test in this case.

In other words, this should work:

{{ entry.type.handle starts with 'meetingsEvents' }}

Tip: When in doubt about the data your working with, or stuff not working like you'd think, it's often a good idea to dump:

{{ dump( entry.type ) }}

This will output all sorts of useful information about the data, e.g. what it actually is (String, Object etc), all its properties and methods etc.


In the context of Craft CMS, Modules typically would be used for adding functionality to the website itself. As such, you'd use it for things that are specific to that project. Check out the article Enhancing a Craft CMS 3 Website with a Custom Module for details.

You can also generate your module scaffolding via pluginfactory.io


Saving a SuperTable field within a Matrix Field

Finally figured this out, I had to delve into the matrix field and get the individual block ids for the Supertable fields.

$matrixBlocks = Craft::$app->getFields()->getFieldByHandle('eventPerformances')->getBlockTypeFields();
$ticketBlockId = (int)$matrixBlocks[2]['id'];
$linkBlockId = (int)$matrixBlocks[3]['id'];

$ticketsField = Craft::$app->getFields()->getFieldById($ticketBlockId);
$ticketsBlockTypes = SuperTable::$plugin->getService()->getBlockTypesByFieldId($ticketsField->id);
$ticketsBlockType = $ticketsBlockTypes[0];

$linksField = Craft::$app->getFields()->getFieldById($linkBlockId);
$linkBlockTypes = SuperTable::$plugin->getService()->getBlockTypesByFieldId($linksField->id);
$linksBlockType = $linkBlockTypes[0];

After casting these to integers and then using that value as the type value when saving the matrix block, it all works!

Full code below, hopefully it will help others out in this situation:

$matrixBlocks = Craft::$app->getFields()->getFieldByHandle('eventPerformances')->getBlockTypeFields();
$ticketBlockId = (int)$matrixBlocks[2]['id'];
$linkBlockId = (int)$matrixBlocks[3]['id'];

$ticketsField = Craft::$app->getFields()->getFieldById($ticketBlockId);
$ticketsBlockTypes = SuperTable::$plugin->getService()->getBlockTypesByFieldId($ticketsField->id);
$ticketsBlockType = $ticketsBlockTypes[0];

$linksField = Craft::$app->getFields()->getFieldById($linkBlockId);
$linkBlockTypes = SuperTable::$plugin->getService()->getBlockTypesByFieldId($linksField->id);
$linksBlockType = $linkBlockTypes[0];

$performancesMatrix = array();
$ticketsMatrix = array();
$linksMatrix = array();
$performances = $event['schedules'][0]['performances'];
$i = 1;

foreach ($performances as $performance) {

     if (array_key_exists('tickets', $performance))
     {
         $t = 1;

         foreach ($performance['tickets'] as $ticket)
         {

             $ticketsMatrix['new'.$t] = array(
                 'type' => $ticketsBlockType->id,
                 'enabled' => true,
                 'fields' => array(
                 'ticketType' => $ticket['type'],
                 'minPrice' => (array_key_exists('min_price', $ticket) ? $ticket['min_price'] : ''),
                 'maxPrice' => (array_key_exists('max_price', $ticket) ? $ticket['max_price'] : ''),
                 'currency' => (array_key_exists('currency', $ticket) ? $ticket['currency'] : ''),
                 ),
             );
             $t++;
         }
     }

    if(array_key_exists('links', $performance))
    {
         $l = 1;
         foreach($performance['links'] as $link)
         {

             $linksMatrix['new'.$l] = array(
                 'type' => $linksBlockType->id,
                 'enabled' => true,
                 'fields' => array(
                     'linkType' => (array_key_exists('type', $link) ? $link['type'] : ''),
                     'linkUrl' => (array_key_exists('url', $link) ? $link['url'] : ''),
                 ),
             );
             $l++;
         }
     }

     $performancesMatrix['new'.$i] = array(
         'type' => 'performance',
         'enabled' => true,
         'fields' => array(
             'performanceDate' => date_create($performance['ts']),
             'duration' => (array_key_exists('duration', $performance) ? $performance['duration'] / 60 : ''),
             'tickets' => $ticketsMatrix,
              'performanceLinks' => $linksMatrix
         ),
     );
     $i++;
 }

$entry->setFieldValue('eventPerformances', $performancesMatrix);


Not sure why you're referencing "entry" in your code, I'd think the code should be:

{% for block in footer.links %}
  {% if block.navigationLinks | length %}

{{ block.navigationHeadline }}

    {# Show the navigationHeadline if it has links #}

      {% for row in block.navigationLinks %}

{{ row.linkLabel }} - {{ row.linkUrl }}

      {% endfor %}

  {% endif %}
{% endfor %}

So, "links" is the matrix on your "footer" global, which you can access from anywhere. You loop over that, get a block for each matrix block, and access "navigationHeadline" and "navigationLinks" through that.


I'm rolling the same thing with

{% extends 'layouts/_entry_layout' %}
{# sets the name for the css file to be pulled #}
{% set pageType = 'search' %}
{% set catSlug = craft.request.getSegment(2) %}
{% set title = craft.categories.slug(catSlug).first() ~ ' Channel' %}

{% block content %}

{% paginate craft.entries.relatedTo(category) as entriesOnPage %}

{{ category.title }}

    {% for entry in entriesOnPage %}
        {% include 'modules/_article_listing' %}
    {% endfor %}

{% include 'inc/_pagination' %}

{% endpaginate %}

{% endblock %}

my article listing module contains the usual things like {{ entry.title }} etc

and pagination include is like so:

{% if paginate %}

{% set currentPage = paginate.currentPage %}
{% set startPage = currentPage - 2 %}
{% set endPage = currentPage + 2 %}
{% if query is defined %}
{% set queryString = "?q=" ~ query %}
{% endif %}

{% if paginate.totalPages > 1 %}

        {% if paginate.prevUrl %}

                &larr;
                Previous Page

        {% endif %}
        {% for i in startPage..endPage %}
        {% if paginate.getPageUrl( i ) %}
        {% if i != currentPage %}

                Page {{ i }}

        {% else %}

            Current Page {{ i }}

        {% endif %}

    {% endif %}
    {% endfor %}

    {% if paginate.nextUrl %}

            Next Page
            &rarr;

    {% endif %}

{% endif %}

{% endif %}


Template Errors with Include on Single Entry

In your current code, the entry variable is actually an instance of ElementCriteriaModel, which is probably the reason you're getting errors.

In order to set entry to an actual EntryModel, you'll need to add a call to first():

{% set entry = craft.entries.id(72).first() %}
...


You could use a task within your plugin for better performance when looping through your records.

Check the TasksService docs and also PowerNap, an example plugin that uses a task.


How to disable template caching? devMode isn't doing it

It is true that devMode does not turn off caching. What I do is define a flag in general.php:

'cacheThings' => true, // true by default, but usually false for dev

and then in my templates:

{% cache if craft.config.cacheThings %}

update
Since version 2.4 there is a new config value: enableTemplateCaching, so all you need to do now is set this false in your development environment.


CraftCMS Redactor is adding  tags to viewable source code... but then removes them when saving

In the Advanced section of your field definition, there are settings for clean-up actions and Purify HTML.

I suggest trying to disable Purify (or use a custom config).


How to restrict access to some section in front-end for admin user only?

One option is to do this:

{% if currentUser.admin ?? false %}

    ...this code can only be seen by admins...

{% endif %}

currentUser is a Global Variable on which you can pass the admin property. ?? is a null-coalescing operator which returns false if the currentUser (if there is one) is not an admin.

Edit:

So if you want to show this section to anyone logged in to the admin or client account in Craft Client, I'd recommend doing the following:

{% if currentUser ?? false %}

    ...this code can only be seen by admins...

{% endif %}

Basically, this says if the current user is logged in, display the contents. Since the only ones with logins are you and the client, this will only display the content to you!

If you'd like for the whole page to only display for certain users (for any unaccepted visitors it will throw a Craft 403 error page), you can add something like this to the top of your template:

{% requirePermission "permissionHandle" %}

(You can find a full list of permissions here.)

I'd recommend the accessCp permission handle if you're wanting to block everyone but the client and admin accounts for Craft Client.


Pass Craft field object to JavaScript function

You have to break it up into individual values before you can pass it through to JS...

{% includeJsFile "/js/homepage.js" %}
{% set myJs %}
   playlistData({
      field1: '{{ myObject.field1 }}',
      field2: '{{ myObject.field2 }}',
      field3: '{{ myObject.field3 }}'
   });
{% endset %}
{% includeJs myJs %}


Is it possible to localize Freeform fields and labels?

You can render the fields by your own and use the twig translate filter and do it with translation files. But I think there is no way to do it via the CP currently.


Publishing entry returns Internal Server Error (1030 Got error 139)

I also tried to change the table engine to MyISAM

That won't work because Craft relies on foreign key constraints that InnoDB provides and MyISAM doesn't support.

There might be some server config/changes you can do to address the issue, but because you're bumping into MySQL/InnoDB limitations, I'd try to address this from an information architecture point of view.

i.e. You've likely got a lot of fields that are probably ending up as text data types in MySQL.  Can you change those to fields that use varchar instead?  Can you logically break up the fields so they make sense inside of a Matrix field?  Matrix fields get their content stored in their own table outside of the main craft_content table, which is where you're likely running into that error.


{{ entry.getAuthor().getPhoto().getUrl() }}

Here is the function. Of course if the author has no photo you'll receive nothing (but an exception). Furthermore this function returns the URL not a HTML tag.


There is a known issue where if you use a variable name 'entry' in any template involved in a Live Preview request (including layout templates), then it can cause the behavior you're seeing.

Some examples are:

{% set entry = craft.entries. ... .find() %}

or

{% for entry in craft.entries. ... .find() %}

The workaround is to rename that variable to something else.  myEntry, for example.


I figured it out by modifying the code from this answer on image transforms. Here's the basics of my markup.

<div class="{% if loop.length == 2 %}grid-one-half{% elseif loop.length == 3 %}grid-one-third{% elseif loop.length == 4 %}grid-one-quarter{% endif %} grid-item">
</div>


Send email to website owner after user registration

I have done something very similar. You'll want to create a plugin for this.

In my case, I am validating email addresses so I was checking against the onBeforeActivateUser event. If you are not validating email addresses, @Lindsey D' answer is where you want to go.

Either way, they will look about like this:
I created a plugin called accounts.

MyPlugin.php

public function init()
{
    /**
     * Event listener for activating a user.
     *
     * @param Event $event
     */
    craft()->on('users.onBeforeActivateUser', function (Event $event) {
        $user = $event->params['user'];

        craft()->accounts->onSendNotificationEmail($user);
    });
}

MyService.php

/**
 * Sends a notification email.
 *
 * @param $user
 * @return bool
 */
public function onSendNotificationEmail($user)
{
    $recipient = $user->email; // get the email address passed in

    $email = new EmailModel();

    $message = '<!DOCTYPE html><title>My Title</title>';
    $message .= '';
    $message .= '
';
    $message .= '
LOGO/BRANDING
';
    $message .= '
';
    $message .= '
Hello,
There has been a new account created on the website.
';
    $message .= '
...your message here...
';
    $message .= '';

    $email->subject = 'New Account Created';
    $email->body = $message;

    try {
        $email->toEmail = $recipient;

        craft()->email->sendEmail($email);
    } catch (\Exception $e) {
        return false;
    }
}

I'm sure there is a cleaner way to get your email body into the CP itself and allow the admin to change the message easily, but this works quick/well.


Turning off a site in multi-site/multi-environment config

The isSystemLive config setting isn't multi-site aware. It sets the entire Craft installation on or off, rather than per site, so you'll need to find a different method to disable domain2.com on the production server.

Untested, but you could try to set the baseUrl for domain2.com to an empty string on production and see if that works.


Break-up Element API Config into partials

I had sometime to review the documentation in more depth;
https://github.com/craftcms/element-api/tree/v1#transformer

An abbreviated example below. Note, I include all transformers in a /transformers directory within /config.

file - craft/config/elementapi.php

  return [
    'endpoints' => [
      // Home
      //
      'api/home' => function() {
        require craft()->path->getConfigPath().'transformers/home.php';
        return [
          'elementType' => ElementType::Entry,
          'criteria' => [
            'section' => 'homepage'
          ],
          'first' => true,
          'cache' => 'PT1M',
          'transformer' => new homeAPI(),
        ];
      },

      // About
      //
      'api/about' => function() {
        require craft()->path->getConfigPath().'transformers/about.php';
        return [
          'elementType' => ElementType::Entry,
          'criteria' => [
            'section' => 'about'
          ],
          'first' => true,
          'transformer' => new aboutAPI(),
        ];
      },

      // Remaining Endpoints...
      //
    ]
  ];
?>

file - craft/config/transformers/home.php

<?php
  namespace Craft;
  require craft()->path->getPluginsPath().'elementapi/vendor/autoload.php';
  use League\Fractal\TransformerAbstract;

  class homeAPI extends TransformerAbstract {
    public function transform(EntryModel $entry) {

      $bodyBlocks = [];
      foreach ($entry->homepageContent as $block) {
        switch ($block->type->handle) {
          case 'gallery':

            $bodyBlocks[] = [
              'gallery' => [
                'thumbnails' => $thumbnails
              ]
            ];
          break;

          // Remaining Fields...
          //
        }
      }

      return [
        'id' => (integer) $entry->id,
        'title' => $entry->title,
        'content' => $bodyBlocks,
      ];
    }
  }


How to get specific single with status live

This should work:

{% set careers = craft.entries.section('careers') %}

{% if not careers|length %}
    {% exit 404 %}
{% endif %}


Just put your javascript file in the templates folder. E.g. place a file called external.js in the folder craft/templates/includes/. Then include it like this <script src="/includes/external.js" type="text/javascript"></script>

I don't know if this is an official way to do it, but it works.


Looking for an advanced form plugin for Craft CMS

To answer your questions in regards to how they will fit with Freeform...

If what you mean by pre-populating fields with existing data is being able to fill fields with data from other elements, Freeform can do this. It allows you to populate fields with data from other Craft Elements or even common Predefined data included with Freeform such as States, Months, Date ranges, number ranges, etc. If what you mean is that you'd like a submitted form to retain its existing data when there's an error upon submitting the form, it can do that as well.
Forms can be duplicated in Freeform.
You have full control over your template formatting in Freeform. You can use one of the default formatting templates included with Freeform (preset for popular frameworks), use one as a starting point and adjust as necessary, or completely customize your own thing.
The best choice here would be to use Freeform's built-in Table field, which allows you to collect and handle repeating data nicely.
Freeform offers a wide variety of field types, and included with them is the necessary validation for each.
File Upload fields are available with Freeform.
Freeform's Conditional Rules feature allows you to show/hide fields based on the contents or selection or check of other field(s). Included in this is also page jumping in multi-page forms.
Freeform offers 5 different ways to send email notifications, and you can have as many different types of email notification templates, and customize them however you please.
It depends what you mean by translatable, but Freeform forms can be translated with static translation files. The CP itself is also translatable.
Freeform has what we believe is fairly comprehensive documentation, and it's always getting better. And when questions or issues arise, you can always contact us for help.
Freeform is the most popular third party form plugin for Craft CMS, and it has a proven history of active development for years. You can preview the meaty changelog filled with countless feature additions, improvements and bug fixes. It's actively developed by Solspace, which has been around and developing software for well over a decade. :)


Setting the position of a Smart Map marker on the front end

Turns out my code was pretty much working but there was another issue in there that was stopping the map marker updating. I've since resolved it.
The original form is huge so here's a cut down snippet of the part that does the marker update in case anyone needs it. This cut-down version isn't tested but should be good.

Incidentally, the "parent element ID" to which I referred is the id of the entry in which your map resides.

Basic location update form (my entry is 'property')

<form id="property-edit__form" method="post" accept-charset="UTF-8" enctype="multipart/form-data">
    {{ getCsrfInput() }}
    {% if property is defined %}
        <input type="hidden" name="action" value="entries/saveEntry">
        <input type="hidden" name="entryId" value="{{ property.id }}">
        <input type="hidden" name="sectionId" value="{{ property.sectionId }}">
        <input type="hidden" name="enabled" value="{{ property.enabled }}">
    {% else %}
        <input type="hidden" name="action" value="entries/saveEntry">
        <input type="hidden" name="sectionId" value="3">
        <input type="hidden" name="enabled" value="0">
        <input type="hidden" name="redirect" value="me/property/saved">
    {% endif %}

            Street Address
            <input class="js-address-part" type="text" name="fields[location][street1]" value="{{property.location.street1 ?? ''}}">

            City
            <input class="js-address-part" type="text" name="fields[location][city]" value="{{property.location.city ?? ''}}">

            County
            <input class="js-address-part" type="text" name="fields[location][state]" value="{{property.location.state ?? ''}}">

            Post Code
            <input class="js-address-part" type="text" name="fields[location][zip]" value="{{property.location.zip ?? ''}}">

            Country
            <input class="js-address-part" type="text" name="fields[location][country]" value="{{property.location.country ?? ''}}">

        <input class="js-address-lat" type="hidden" name="fields[location][lat]" value="{{property.location.lat ?? ''}}">

        <input class="js-address-lng" type="hidden" name="fields[location][lng]" value="{{property.location.lng ?? ''}}">

<button class="js-address-lookup">Lookup address</button>

        {% if property is defined and property.location.hasCoords %}

            {% set options = {
                height: 300,
                width: '100%',
                zoom: 11,
                markerOptions: {
                    icon: '/images/map-marker.png'
                    },
                }
            %}
        {% else %}
            {% set options = {
                height: 300,
                width: '100%',
                zoom: 4,
                center: { 'lat': 51.499998 , 'lng': -0.1166662},
                markerOptions: {
                    icon: '/images/map-marker.png'
                    },
                }
            %}
        {% endif %}

        {% if property is defined %}
            {{ craft.smartMap.map(property.location, options) }}
        {% endif %}

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

And some Javascript to do the business (using jQuery here).


How do I set a controller for my homepage

Ok, maybe you can check if the entry in the matrix block is still valid (non-expired) and if that's not the case, just don't render the matrix block? Put everything in a simple if statement?

Something like this (hasn't been tested, use it as an example of what the actual code would be):

{% for block in entry.myMatrixField %}
    {% if block.type == "something" %}
        {% if block.entry.status != 'expired' %}
            {{ block.entry.title}}
        {% endif %}
    {% endif %}
{% endfor %}


Migrated Server, Now Getting Logged Out Constantly

Most likely wherever Apache/PHP is configured to save session files doesn't exist or isn't writable.

If you've got the overridePhpSessionLocation config setting set to true, then that will be in craft/storage/runtime/sessions folder.


I bet this trips up a lot of people at first, but your asset field will return a ElementCriteriaModel, not your image.

To get to image, you need to fetch it. If your field has only one image, you will do something like this:

{# Fetches the first image #}
{% set image = entry.featureImage.first() %}
{# It's good to check if you actually have an image before trying to get the url #}
{% if image %}
    {{ image.url }}
    {# Or alternatively #}
    {{ image.getUrl() }}
    {# If you want to get a specific transform: #}
    {{ image.getUrl('transformHandle') }}
{% endif %}

The Assets fields documentation got some good examples on the different use cases.


You can take a look at the guide Enabling CSRF Protection

<script type="text/javascript">
    window.csrfTokenName = "{{ craft.app.config.general.csrfTokenName|e('js') }}";
    window.csrfTokenValue = "{{ craft.app.request.csrfToken|e('js') }}";
</script>

var data = {
    // ...
};

// Add the CSRF Token
data[csrfTokenName] = csrfTokenValue;

$.post('/some/url', data, function(response, textStatus, jqXHR) {
    // ...
});


Does Craft have a bookmarklet to quickly post/save content from the web?

Nothing from P&T and I haven't seen one floating around the web, either.


Images Uploaded in CMS not showing on mobile [desktop is fine]

From Craft's POV, there's no difference between desktop and mobile.  I'd check your CSS to see if you're changing how things are displayed depending on the @media query breakpoints.


How to check if an Image Transform exists?

Like Brad says, you'd need to write a custom plugin – specifically, one that provides a Template Variable class exposing the AssetTransformsService's getTransformByHandle method.

The variable class could look something like this:

class MyPluginVariable
{

    public function imageTransformExists($handle)
    {
        // Returns null if transform doesn't exist
        return craft()->assetTransforms->getTransformByHandle($handle);
    }

}

Then, you'd be able to test for named image transforms in your templates like this:

{% if craft.myPlugin.imageTransformExists('thumb') %}
    ...
{% endif %}

If you're not familiar with plugin development, it might be useful to use the Business Logic plugin as a starting point – it even has a Variable class which you could just drop the above imageTransformExists method into.


I was able to get to the bottom of this and the problem was that 2 columns in my CSV file had the same name.

If you have a similar problem check the "craft_import_log" table in your database. You will find the error reporting for the import plugin there. The error I received was "Columns and data did not match, could be due to malformed CSV row."

I ran my CSV through an online checker and it informed me that there were duplicate column headings. Renaming one of the columns fixed my issue.


Array expecting string error when fieldtype is used within matrix

It appears as though $settings['colours'] is an array... which you're then trying to trim and explode.

Can you var_dump($settings['colours'])?

p.s. Nice to see "colours" spelt "correctly" :)


This actually turned out to be a max_execution setting in the php.ini MAMP was using after increasing it from 30 seconds everything worked fine.


Individual persistent property per item in stock

You can use the beforeGenerateLicenseKey event and query for a custom key in your custom table and set the license key

Event::on(License::class, License::EVENT_GENERATE_LICENSE_KEY, function(GenerateKeyEvent $e) {
    $licenseKey = (new Query())
                      ->select(['mykey'])
                      ->from('{{%mytable}}')
                      ->where(['used' => false])
                      ->scalar();

    $e->licenseKey = $licenseKey;
});

And when you insert new keys in your custom DB table, you can change the stock of your variant accordingly

$variant = //grab the variant you need for your product
$variant->stock = (new Query())->from('mytable')->count();
// store the variant


I'm not sure this is a really a Craft-specific question, but here's a basic strategy:

Build your nav and pages to work without any Ajax calls. Make sure your nav is output consistently (e.g. in <nav class="primary-nav") as well as the content of the page (e.g. in <div class="main">).
Now implement your JavaScript. You want to (a) intercept navigation link clicks to stop a full page reload, (b) Ajax in the new content, (c) move the active class to the clicked navigation link, and (d) change the URL to the new page address. Make sure to use History.js to smooth out any difference in browser implementation of HTML5's history API (including pushState).

Here's a demo (and code) I cooked up with static HTML. It's based on Andrew Fricke's post titled Rolling your own PJAX Implementation with History.js


Multi sites: how to give each site a home single entry?

It's well explained in your section settings in the CP: there is a table with the settings for each site with a hint to leave the field blank if it should be the homepage.

If you want to have a different entry as the homepage for another site create a new single section for that site.

Single Entry 1

-----------------------------------------------------
| site              | url            | template     |
-----------------------------------------------------
| english, disabled |                |              |
| german, enabled   |                | index.twig   |
-----------------------------------------------------

Single Entry 2

-----------------------------------------------------
| site              | url            | template     |
------------------------------------------------------
| english, enabled  |                | index.twig    |
| german, disabled  |                |               |
------------------------------------------------------

That way users won't be able to edit the homepage entry from other sites.
Another approach would be to limit the site permissions for your editors so they'll only be able to edit the elements which are connected to their site.


I'm searching for a option to remove all unused images

Best way to handle this is probably with a console command provided by a module.

The console command would need to fetch all asset IDs that don’t have any corresponding rows in the relations database table.

use Craft;
use craft\db\Query;
use craft\db\Table;
use craft\elements\Asset;
use yii\console\ExitCode;
use craft\helpers\Console;

public function actionPurgeUnusedAssets(): int
{
    // Find any asset IDs that aren't related to anything
    $assetIds = (new Query())
        ->select(['a.id'])
        ->from(['a' => Table::ASSETS])
        ->leftJoin(Table::RELATIONS . ' r', '[[r.targetId]] = [[a.id]]')
        ->where(['r.id' => null])
        ->column();

    if (empty($assetIds)) {
        $this->stdout('No unrelated assets to delete.' . PHP_EOL);
        return ExitCode::OK;
    }

    // Now fetch and delete them
    $assets = Asset::find()
        ->id($assetIds)
        ->all();

    $this->stdout('Found ' . count($assets) . ' unrelated assets.' . PHP_EOL);

    foreach ($assets as $asset) {
        $this->stdout(" - Deleting asset {$asset->filename} ... ");
        Craft::$app->elements->deleteElement($asset);
        $this->stdout('done' . PHP_EOL, Console::FG_GREEN);
    }

    $this->stdout('Finished deleting unrelated assets.' . PHP_EOL);
    return ExitCode::OK;
}

Then, you can set up a cron job on your server that hits this command every 24 hours.

0 0 * * * /path/to/project/craft your-module/purge-unused-assets


"An error occurred while generating this PDF." in Commerce 2

Looks like there was a broken include in the order template. Sorted now though thanks.


I just did some testing of this. I thought I noticed the same thing, but then realised that I created and added the field to my section (a single) only after it already existed. In that case the defaults didn't show. But then I added the field to a channel section and created a new entry and the defaults show in that case.

So I think the reasoning is that it won't populate defaults on an already existing entry as these could easily go unnoticed by someone editing and end up being saved to the entry when unintended.


Display all fields without knowing object type?

You can

<pre>
{{ dump(myObject) }}
</pre>

And see it's type and attributes. You can as well use {{ dump(Object.getAttributes) }} with nearly everything in Yii2. If it's just about getting to know what object you currently have this function will be your friend once you know how to use it. Another approach would be much simpler yet more powerful: take a look at the source code or enable intellisense for your IDE and let your IDE show you everything


Can I call methods on an object represented by a string variable?

Twig's attribute function allows you to set the method as a string and not the object. The object has to be an actual object, even with that function.

{% set object = craft.entries.order('postdate').last() %}
{% set method = 'title' %}

{{ attribute(object, method) }}

The only workaround I can think of is to link your object-representing string to an actual object in your template. But this makes little sense as you probably wouldn't have set it as a string to begin with, hehe. Anyways:

{% if string == "craft.entries.order('postdate').last()" %}
    {% set object = craft.entries.order('postdate').last() %}
{% endif %}

{{ attribute(object, method) }}


I'm not sure I'm following the question 100%, but if you want to search for an "exact match" you can use put your search term in quotes.  i.e. "search for this exact phrase".  And if you want to find an exact match in a particular field, you can use fieldHandle:"exact match".

You can see the full search syntax list here: https://craftcms.com/docs/searching


Upgrading to 3.6 Impossible With PHP 8 Installed

So probably the best thing you can be doing is doing your updates locally, testing them, and then pushing them to the production environment.
You can read more about it in the Updating Craft CMS without Headaches article.
You still have the opportunity to do this here... get a local dev environment set up, pull down your code and database, then get it up and running on a PHP version such as PHP 7.4 that will work with older versions of Craft as well as Craft 3.6.
Then do the update locally, and deploy the update to your production server.


siteUrl config and Control Panel conflict

The siteUrl config setting is not meant to be added under environmentVariables.

'test.dev' => array(
    'siteUrl' => 'http://test.dev/',
    'environmentVariables' => array(
        // ...
    ),
    // ...
)


Search matrix for blocks with upcoming dates

Here’s how you would do that:

{% set futureEvents = entry.myMatrixField.myDateField('>= '~now) %}

{% for event in futureEvents %}
    {{ event.description }}
{% endfor %}

Update:

This actually hadn’t worked as I expected to, but it does as of Craft 2.3.


Composer Issue When Doing exec From a Plugin

The problem seems to be tied to Composer not having the correct permissions. Will work with our IT team to update so Composer can write appropriately when initiated from Craft.


Importing voucher codes from Espresso Store to Verbb Gift Vouchers

I think you'd be better off creating a quick module with a controller method to import your voucher codes, to make sure Craft (and Verbb Gift) create all the necessary table rows for the vouchers to work (code is untested, but just to get an idea):

use verbb\giftvoucher\elements\Voucher;

public function actionCopyVouchers()
{
    $esVouchers = Craft::$app->db->createCommand()->select('*')->from('es_vouchers')->all();

    foreach ($esVouchers as $esVoucher) {
        $voucher = new Voucher();
        $voucher->field = $esVoucher->field;
        $voucher->anotherField = $esVoucher->anotherField;
        // ... Whatever your voucher needs ...

        Craft::$app->getElements()->saveElement($voucher);
    }
}


Not in the config file, but you can from index.php using the CRAFT_TEMPLATES_PATH constant:

define('CRAFT_TEMPLATES_PATH', '../templates/');


TL/DR: MySQL is horrible.

The craft_searchindex table is the only table that uses MySQL's older MyISAM storage engine, instead of InnoDB (like the rest of the tables), because InnoDB didn't add support for MySQL's full text search capabilities until very recently (version 5.6.4).

One of the many drawbacks of the MyISAM storage engine, as you've discovered, is that the tables using it can crash easily.  The crashes can occur for a variety of reasons... low disk space, firmware issues, buggy MySQL, sudden server reboot, etc.

From the command line, you can run a "repair all" like so:

mysqlrepair -A --auto-repair
mysqlrepair -A -o

Or start a test that might help you diagnose why it's crashing:

mysqlrepair -A -c

Also, if you know you're running > MySQL 5.6.4 across all of your environments, you can change the storage engine for that table from MyISAM to InnoDB.


Craft as an API provider & authenticaton

It sounds like you're not necessarily interested in authenticating against Craft's current users, but you just want some type of header authentication in place.

If you set those header (via whatever means) in the API request, you can have a plugin's controller read those via HeaderHelper::getHelper($headerName) and perform whatever authentication logic that you require.

If authentication passes, let the request go through, if not, you can throw new HttpException(503);.


Incorrect user-level lock name - Local Vagrant Environment - Craft 3

I just  ran into the exact same error on my Vagrant/Homestead environment when creating a field just with the lock name '/home/vagrant/code/craft/storage/runtime/compiled_classes/ContentBehavior.php'.

After getting this error the page cannot be accessed at all.

I'm using SuperTable, too.

The error itself seems to come from MySQL 5.7 where there is a character limit for the user-level lock names of 64 characters. Here the GET_LOCK statement fails. I just don't know how to fix it right now.


How to manage a large database when upgrading from 2.0 to 2.1

In my specific case - upgrading from 2.0.2551 to 2.1.2570 - the issue was caused by there being millions of rows in the craft_entryversions table. One of the migrations in the update needed to loop through every row in that table and do something to it and therefore it took ages.

Simply emptying that table solved the upgrade process for me.

Caveats

Obviously this deletes all your entry versions...so, each entry will just exist at its last known 'live' state. This wasn't a problem for me - but might be for you.

Its worth noting that this shouldn't affect any drafts users might have made as they are stored in a separate craft_entrydrafts table.

Thanks to Fred Carlsen for helping me think aloud...


How can I restrict access to the Control Panel to a single port?

First set your web server up so the full website gets loaded from both the external ports (e.g. 80 and 443) as well as your internal port (let's say 9001).

Then open your index.php file, and add this to the top of it:

// Restrict CP access to port 9001
if (
    $_SERVER['SERVER_PORT'] != 9001 &&
    isset($_GET['p']) &&
    preg_match('^\/*admin(\/.*)?$/', $_GET['p'])
) {
    http_response_code(403);
    echo 'You are not authorized to access this area.';
    exit();
}


Although not related specifically to Craft, we built https://www.jelliscraig.com.au website using CraftCMS with all property listing data is stored in ElasticSearch. We use a simple plugin for the ElasticSearch PHP client but the integration is front-end only, for the most part.
We have been testing pushing Craft generated content into ElasticSearch via the element API and in theory its a workable solution however for our specific situation we see no huge benefit in storing all general content externally.


Smart Map - Setting single map with multiple pins

According to the docs, locations has to be an array of elements or an ElementCriteriaModel
if you want to display multiple markers.
{% set mapEntries = craft.entries.section('markets') %}
{{ craft.smartMap.map(mapEntries, options) }}


How to upload assets without user interaction?

Answering my own question for reference.
I was tunneling too hard on the PHP, a simple bash script takes care of the upload.
# assuming the image is already downloaded and no CP-login required
curl -F assets-upload=@/path/to/image mycraftsite/admin/actions/assets/uploadFile

EDIT
Better answer: Thanks to this answer I discovered the insertFileByLocalPath() function in AssetsService.
  $entry = craft()->entries->getEntryById($id);
  if($entry && isset($entry["imageFetchUrl"])) {
    $url = $entry->getFieldValue("imageFetchUrl");
    $tmpfname = tempnam("/tmp", "UL_IMAGE");
    $img = file_get_contents($url);
    file_put_contents($tmpfname, $img);
    craft()->assets->insertFileByLocalPath($tmpfname, 'fetchedImg.jpg', $myFolderId);
  }


Filter entries by month regardless of year using custom Date/Time and paginate them

I think you are right and there's no chance to do what you want with parameters on a single ElementCriteriaModel.

You could definitely do it with many queries, the first one to get your years array, then one for each year. Merging them is simple with Twig's merge filter. But then you'd end up with a manually composed array of entry models and don't have the convenience of a single ElementCriteriaModel. Methods like getNext() or – important in your case – the {% paginate %} tag won't work with an array of entry models!

Let's skip the paginate problem for now and look at that query flood, you'd produce. Sure, Craft has the {% cache %} tag, but if your entries are modified regularly, there'll always be people who access the uncached version.

But what about another solution, why not do a single query to get all your "messages" entries and filter them in your template with a simple conditional:

{# Get all `messages` entries #}
{% set entries = craft.entries.section('messages') %}

{# Loop through all entries with a `messageDate` month of `myMonth` regardless the year #}
{% for entry in entries if entry.messageDate|date('m') == myMonth %}
    {{ entry.title }}
{% endfor %}

You'd still have no solution yet for your pagination problem, but this should be way less expensive on performance, and it's really easy to implement.


Cache HTTP and HTTPS seperately using {% cache %}

Something like this would work:

{% if craft.request.isSecure() %}
    {% set cacheKey = 'secure' %}
{% else %}
    {% set cacheKey = 'insecure' %}
{% endif %}

{% cache using key cacheKey %}
    ...
{% endcache %}

See here for more info.


There are three types of sections in Craft: singles, structures, and channels. You can use entry.section.type to test if the current page is displaying one of these section types.

{% if entry.section.type == "channel" %}

This is a channel

{% elseif entry.section.type == "single" %}

This is a single

 {% elseif entry.section.type == "structure" %}

This is a structure

 {% endif %}


I wrote the Retour plugin; it will definitely work. However it only kicks in after 404 error is thrown by Craft. So if some route resolves to the URL in question, it won't kick in (because, by definition, it is then not a 404)


Accesing craft.categories.slug ids within a MatrixBlock for search query

I wanted to post this in case someone can use a portion of it to help with their search queries. This is what we came up with, works in combination with our three other category dropdowns (all four can be multiple selections), plus some custom Javascript.

{% set categoriesArray = ['and'] %}

{# Institution #}
{% set searchInstitution = craft.request.getParam('institution') | replace({'|' : '\''}) %}
{% if searchInstitution is not empty %}
{% set institutions = craft.categories.search( searchInstitution ) %}
{% set categoriesArray = categoriesArray|merge([{targetElement: institutions, field: 'position.institution'}]) %}
{% endif %}

JS

var institutionNames = cbxInstitution.toArray()
      .reduce(function (p, c) {
        if (c.checked) p.push(c.value);
        return p;
      }, []);
    inInstitution.val(institutionNames.map(function(v){ return "|"+v.trim()+"|"; }).join(" OR "));


How can I cache a list of entries with pending postDates and have it automatically invalidate the cache appropriately?

Easy! Get the most soonest upcoming pending entry, and use until:

{% set firstPending = craft.entries({
  section: 'articles',
  status: 'pending',
  order: 'postDate asc'
}).first %}
{% set cacheUntil = firstPending ? firstPending.postDate : now|date_modify('+1 year') %}

{% set content %}
    {% cache until cacheUntil %}
        ...
    {% endcache %}
{% endset %}

Note that this solution requires Craft 2.2.2598 or later.


With two EC2 Craft instances, the Control Panel session keeps expiring

Easiest solution: if AWS supports "sticky sessions" at the load balancer level, then you should enable to to ensure that the user gets sent back to the same EC2 instance that their session was created on.

Next easiest: create an NFS share and use https://secure.php.net/manual/en/function.session-save-path.php on all EC2 shares so all EC2 instances read/write to the same place.  You'd also want to set the Craft appId and validationKey config settings to be consistent across all of the EC2 instances.


Following from Lindsey D's answer, I just wanted to point out you can skip manually mapping the weekday names by calling craft.i18n.getLocaleData().getWeekDayName() like so:

{% set day = craft.i18n.getLocaleData().getWeekDayName(dayIndex) %}

It's also worth mentioning, you can check for empty values to indicate the store is closed.

E.g.,

{% for dayIndex,dayHours in companyInfo.storeHours %}

  {% set day = craft.i18n.getLocaleData().getWeekDayName(dayIndex) %}

  {{day}}: {{ (dayHours.open is empty) ? 'CLOSED' : dayHours.open|date('g:i a') ~ '-' ~ dayHours.close|date('g:i a') }}

  <br>

{% endfor %}


For the field type you could use a Super Table field, with columns for the times, the class and the teacher. For the class and teacher column you could consider using an Entries or Categories field, this makes sure the classes are named consistently and you could have links to the classes' description or the teacher's about page.

I would probably create one of these Super Table fields for each weekday and just list them one below the other in your entry type or global set. Is there mulitple rooms or any other reasons to create multiple schedules, than have them in a channel section (ordered by title) or a structure. This could also be handy in case you want to store schedules for each year or season. The user could create the upcoming schedule and it automatically becomes active with the start or the new season (set an expiry date and always pick the latest entry).

Here's an example for school classes:


You don't need to create your own symbol map - it exists as a yii translation:

{% set localeData = craft.i18n.getLocaleData() %}
{% set currencyIso = 'USD' %}

{{ localeData.getCurrencySymbol(currencyIso)  }}


Why is this Twig code generating large numbers of DB queries?

The solution is below.
EDIT: only for MySQL 5.7.4 and lower! Higher versions break.

For whatever reason, the mechanics of the group filter in this case was producing a new query for every Entry. Below, resolves this by doing the same job in a more performant way. I'm not entirely sure of the mechanics of how this works, but the answer was supplied over on the Discord support channel and I thought it worth cross-posting to here. Thanks Sebastian Lenz!

{% cache globally %}
    {% set postDates = craft.entries({
        section: 'newsItems',
        select: 'postDate',
        limit: null,
        groupBy: ['DATE_FORMAT(postDate, "%Y-%m")'],
    }).column() %}

News Archive

            {% for year, postDatesInYear in postDates|group("object|date('Y')") %}

                    {{ year }}

                        {% for month, postDatesInMonth in postDatesInYear|group("object|date('m')")|reverse(true) %}

                                    {{ postDatesInMonth[0]|date('F') }}

                        {% endfor %}

            {% endfor %}

{% endcache %}


Redactor extension plugin loading JS before Redactor.js

You need to alter your properties.js and table.js files. Instead of assigning the plugin function to $.Redactor.prototype you should assign it to the RedactorPlugins object.

Standard Redactor Plugin setup:

$.Redactor.prototype.myplugin = function() {
    return {
    // Plugin code here...
    }
}

Craft CMS Redactor Plugin setup:

// Initialize the RedactorPlugins object if it doesn't exist
if ( !RedactorPlugins ) { var RedactorPlugins = {}; }

// Assign the redactor plugin function
RedactorPlugins.myplugin = function() {
    return {
    // Plugin code here...
    }
}

I'm not sure where the documentation on this is, but you can see it in Pixel & Tonic's own RedactorClips plugin here:  https://github.com/pixelandtonic/RedactorClips/blob/master/redactorclips/RedactorClipsPlugin.php


That error indicates a problem with the data in your database.

The craft_assetfolders table has a parentId column that is a foreign key reference to its own id column.  For whatever reason, that parentId column has a value that doesn't exist in any of the id columns, hence your errors.

Some common causes include:

Someone manually editing database values.
A botched import/export script when backing up/restoring databases.
Having multiple Craft installs (maybe across environments) pointing to the same cloud based Asset source (S3, Google Cloud, etc.) and someone deletes/moves/etc. an Asset on one environment making the other one out of sync with reality.


Adding markers to map from field in entries within section

Author of Smart Map here...

It sounds like your locations are in a section (a Structure is a type of section). The first line of your solution is exactly what you'd need to get the locations value.

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

{{ craft.smartMap.map(locations) }}

Just to clarify...

Are you using the "Address (Smart Map)" field to store your addresses?
And do each of those addresses contain "Latitude" and "Longitude" values?

If so, the code example above should definitely work for you!


What is the best way to create breadcrumbs based on a structure?

Got it!

{% if craft.request.segments %}

Home

                {% for crumb in entry.getAncestors() %}

{{ crumb.getLink() }}

                {% endfor %}

{{ entry.title }}

{% endif %}


How to use the same category group as a filter on multiple channel sections?

I would use a dynamic route instead of the path and template assigned in the category group. If you want the urls to be /Steve/B and /Bob/B, the route would look like {tag}/{slug}. Then in the template, fetch the channel using tag, and the category handle using slug.

Fetching the category:

{% set category = craft.categories.group('categoryGroup').slug(slug).first %}
{% if not category %}{% exit 404 %}{% endif %}

Fetching the entries:

{% set myEntries = craft.entries.section(tag).relatedTo(category) %}


Craft CLI RC1 Connectivity Issues with MAMP Pro

I gave everything a try, but the only thing that worked for me was ensuring "Allow network access to MySQL" was ticked in MAMP.

Screenshot: http://c42.co/Ur30EJ


Add an assets field to a field type plugin template

I don't know enough about your end goal, but it almost sounds like what you're trying to do is what Craft already does very well. If you're just trying to save some time on Assets custom field creation, you might consider checking out FieldManager which lets you import/export fields across projects.


Can You Make a Custom Field with multiple columns?

If your custom field needs more than the default column to store it's data you can create your own custom table (or tables) and store your data however you need to.

This involves a few things:

Create a Record that defines your database table
Save the data to the custom table
Retrieve the data from the custom table

Create a Record that defines your database table

To create a Record, take a look at the Craft Records documentation.  The Record defines the columns in your database table and that custom table will get created when you install your plugin, and removed when you uninstall your plugin. So, after you create your Record, go ahead and re-install your plugin to get the database table to appear in the database and ensure it's the schema you need.

Save the data to the custom table

Now that you have your custom table, you can save data to it.  In your Fieldtype Class CustomPlugin_CustomFieldType.php you can do so using the onAfterElementSave() method.

public function onAfterElementSave()
{
  // $this->element will give you access access to the Element Model
  // your field is associated with (For example, EntryModel, CategoryModel, etc).

  // $this->model will give you access access to the FieldModel
  // your field is associated with.

  // craft()->request->post will give you access to the post data
  // submitted on the request.

  // Once you have retrieved and modified the data you want to save,
  // you can go ahead and save it to your custom table
}

Retrieve the data from the custom table

To populate your field, you'll retrieve your data from your custom tables in the getInputHtml() method.  In the example below, I'm using calling the getCustomFieldValues() method from the service layer which would query the database and give me back the data I need to hand off to my template to display:

public function getInputHtml($name, $value)
{
    $values = craft()->customPlugin->getCustomFieldValues();

    return craft()->templates->render('customplugin/fields/input', array(
        'name'       => $name,
        'values'     => $values
    ));
}


Changes made in home page not displaying

Have you read this?

SCSS needs to be compiled and the page is loaded with the compiled CSS files, the SCSS references are used only for easier debugging and development. Seeing a change during inspection, does not necessarily mean that the CSS file changed, maybe there was a compilation error or something.


Change Freeform redirect URL according to checkbox field

This should be doable. If you have a field in your formatting template with the name formReturnUrl, when checked, it would override the Freeform return URL. You'd likely need to manually hardcode this into your form template code though:

<input type="checkbox" name="formReturnUrl" value="{{ siteUrl }}freeform-demo/bootstrap/my-url" />


When uploading assets what determines the maximum file size?

Craft itself, limits the filesize only in the maxUploadFileSize. Default: 16MB

However Craft gets limited by:

PHP: Has a few values which might cause the problem:

memory_limit
max_input_time
upload_max_filesize
post_max_size

AmazonS3: If not limited by a policy value, the default is 5GB.

User: Sometimes it can be just a Browser issue causing the problem.


How do I find the path to the public folder?

Lots of good discussion on how to do this and the pros/cons of each here: https://stackoverflow.com/questions/4645082/get-absolute-path-of-current-script

In short, the most reliable way is to use PHP's debug_backtrace.

$debugTrace = debug_backtrace();
$initialCalledFile = count($debugTrace) ? $debugTrace[count($debugTrace) - 1]['file'] : __FILE__;
$publicFolderPath = dirname($initialCalledFile);


Currently there isn't a native way to do this, but you could write a plugin which would work like this:

Wait for an event like: content.onSaveContent or entries.onSaveEntry
Get all users from a specific usergroup using the ElementCriteriaModel.
Use the EmailService to send a mail to each of them.

.

Quick-and-Dirty:

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

    //Event: onSaveEntry
    craft()->on('entries.saveEntry', function(Event $event) {

        //Get all users from UserGroup
        $user_criteria = craft()->elements->getCriteria(ElementType::User);
        $user_criteria->groupId = '1';
        $users = $user_criteria->find();

        //Send to each User
        foreach ($users as $user) {
            //Send Mail
            $email = new EmailModel();
            $email->toEmail = $user->email;
            $email->subject = 'Heyyyyy';
            $email->body    = 'How you doin?';

            craft()->email->sendEmail($email);
        }
    });
}


Thanks for asking about this, Cole!

There was a bug that was causing rsortAs to return erroneous results. The issue is fixed in the 1.0 release.

Grab yourself a fresh copy and you should be squared away.


Can I Configure Redactor to Automatically Add a Class to Img Tags?

Found this plugin doing some digging https://github.com/mmikkel/Retcon-Craft. It looks like it can achieve what you need - appending existing attributes (including class names) by applying a filter to your Redactor field in your Twig template.


How I can sort my entry that belong to 3 section on date?

Try chaining the sections together like:

{% set allEntries = craft.entries({
  section: ['blog', 'news', 'caseStudies']
}).orderBy('elements.dateCreated asc').all() %}

Then

{% for entry in allEntries %}
   <span>
       {{entry.nameSection}} | {{entry.dateNews|date("F  d, Y")}}
   </span>

   <h3 class="title post-title">
       {{entry.title}}
   </h3>
{% endfor %}


The free shipping flag on individual products stops costs being calculated by any shipping rule that is a per item rate or weight rate.

See https://craftcommerce.com/docs/product-model#freeshipping


The information that shows up on in the admin/feed-me/logs portion of your Control Panel is pulled directly from the Feed Me logs on the filesystem at storage/logs/feedme.log.

So you'd need to write a little plugin that parsed those files and exposed the data you want back to the template to display it.


Day and month names ignore certain formats in date filter and revert to number

This is a bug in the latest version of Craft specific to Norwegian locales that will be fixed in the next (post 2.3.2643) release.


How to override default root URL of plugin?

This works for me:

public function registerCpRoutes()
{
    return array(
        'settings/plugins/pluginname/index' => 'pluginname/index'
    );
}


In your general.php for a production site you'll probably see "allowAdminChanges" set to false. This is not an inconsistency, this is how it is supposed to work.
Every change you make on your local development will be added to a project config file ( yaml file in your config folder ) and fields / sections / settings you create locally will then automatically be synced into your staging or production environment, the reason admin changes aren't allowed by default in there is simple, if you make changes in many places, the project.yaml file will be inconsistent and you'll run into a lot of issues trying to sync your install across different environments.


Sprout Forms: Map Element ID to Content Field on Save Entry Event

You're almost there, as you can see on the SproutForms_EntriesService Class at line 197 we add a SproutForms_OnSaveEntryEvent. When this event is fired you can get the form entry submitted within the param 'entry'. All you need to do is add a listener to catch this event, please go ahead and add the following code to the init() function of the plugin of your custom field type:

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

        // Let's assume that your field handle is "custom"
        $entry->setContentFromPost(array(
            'custom' => $entry->id,
            )
        );
        // save it again. (avoid an infinite loop using sproutForms()->entries->saveEntry)
        craft()->elements->saveElement($entry);
    });


Query entries relatedTo multiple categories in controller

You need to pass an array of element IDs, where the first index is "and" – just like in your template (Twig) code – to targetElement. Basically, this just means that you need to prepend the string "and" to your array of IDs.

Something like this should do it:

...

$prodCriteria->relatedTo = array(
    'targetElement' => array_merge(['and'], $catIds),
);


FreeForm fields: Need access to customAttributes

A suggestion from Freeform support:

  The only way you might be able to achieve this would be if you used a regular Text field (inside of Composer), and then override the formatting template to manually render the field as a select dropdown and populate the options dynamically. Actual fields with options such as Select fields need to have all of their options pre-defined inside Composer, which is why it wouldn't work otherwise. Using the element populators could almost get you there, but it doesn't allow dynamic filtering like what you'd need.


Can you lookup the value in a key-value array with the value in an entry field?

Two options here ...

{% set transformParams = { width: 1250, height: 1250 * aspectRatioSetting[entry.aspectRatio] } %}

Or just give the select field a value that represents the number, not the word. So set a value of 0.75 instead of four_three, and let the label be Four/Three (or whatever seems fit).


Getting custom user attributes in a service, they return NULL

Here's some code that should return categories related to a user:

$criteria = craft()->elements->getCriteria(ElementType::Category);
$criteria->relatedTo = craft()->userSession->getUser();

return craft()->elements->findElements($criteria);


Three duplicated guest entries posted on form submision

The site is running through CodeKit compiler connected to MAMP server. This was odd because it has never happened before with same configurations but When I run the site directly from MAMP server the problem disappeared.

But I have no idea why compiler was causing that.


First thing I recommend is to read through the Search Form guide from the Craft documentation.
To explain the rest I'll add some comments to the example code.

form.html

{# Use the `group` filter to get the years, entries were posted in #}
{% set entries = craft.entries.section('news') %}
{% set entriesByYear = entries|group('postDate|date("Y")') %}

<select name="year">

    {# Go through the `year` groups #}
    {% for year, entries in entriesByYear %}
        <option value="{{ year }}">{{ year }}</option>
    {% endfor %}

</select>

results.html

{# Get the params #}
{% set year = craft.request.getParam('year') %}

{# Compose a param in this format: 'and, >= 2014-01-01, < 2015-01-01' #}
{% set dateParam = 'and, >= ' ~ year ~ '-01-01, < ' ~ (year + 1) ~ '-01-01' %}

{# Query and loop through the entries #}
{% set entries = craft.entries.section('news').postDate(dateParam) %}

{% if entries|length %}
    ...
{% endif %}


How to set a field of an asset from within a plugin

To save a custom field value on an Asset, you'll first need to pull the actual AssetFileModel, set the custom attribute on the Asset's ContentModel, and finally re-save the Asset.

The following example assumes you've set a field photoId on your asset source:

$fileId = $response->getDataItem('fileId');
$asset = craft()->assets->getFileById($fileId);
$asset->getContent()->setAttribute('photoId', $photo['PhotoId']);
$success = craft()->assets->storeFile($asset);


This is all covered in the Craft CMS documentation:

{% for option in entry.<FieldHandle> %}
    Label: {{ option.label }}
    Value: {{ option }} or {{ option.value }}
{% endfor %}


That cURL 51 error usually means that your server doesn't understand the SNI SSL certificate we have installed at https://craftcms.com and https://craftcdn.com.

Technically there are 3 things a server needs to recognize SNI SSL certs:

Using a version of cURL that supports it, at least 7.18.1 (8 years old: https://curl.haxx.se/changes.html)
Using a version of cURL compiled against a library that supports SNI, e.g. OpenSSL 0.9.8j (depending on the compilation options some older versions. 7 years old: https://www.openssl.org/news/changelog.html)
Using TLS 1.0 at least (not SSLv3)

Once the box Craft is on meets those requirements, it should start working.


Customize elementSelect Field's Modal Table Layout

You should be able to accomplish what you want with a combination of the getTableAttributeHtml() hook and the modifyEntryTableAttributes() hook. You may be able to use the parameter $source from modifyEntryTableAttributes() to filter out index vs modal.

Check out this post for a more detailed description.


Structure(s) vs. Categories for product catalog

I find it difficult sometimes to choose between a category group and a structure, so for me it mostly boils down to semantics.

A brand can be both a structure entry and a category. If you're going to have pages with information about the brand/product faily/product, and they will be available in some kind of menu to be browsed by itself, I think I'd go with a structure. If, on the other hand, they are only going to be used for filtering and organizing, a category group feels more appropriate to me.

From what you've described, I think I'd go with:

Products (structure)
Accessories (structure)
Brands (category)
Product family (category)

But as I said, it depends a lot on the specifics of your content.


Password protect whole staging site. Redirect to original page not working

{% requireLogin %} is intended for use with your own login form on the frontend rather than the standard /admin one. From the docs for loginPath:

  The URI Craft should use for user login on the front-end.

Which means you create your own frontend login form, and set that as the loginPath. As you don't have that, it's defaulting to the default login instead, which redirects users to the admin dashboard instead of the page they were on.


Getting entries from multiple categories

OK resolved now - client slug mis-spelling! thx


getUrl using my original develpment server domain

Have you checked the path of the asset source the image is in? Sounds like that might still be the old server's path.
Best practice is to use Environment-specific variables in your config file, and then use those in you Asset Source settings as well.

So, use {basePath}assets/site as your File System Path for instance (if you've used basePath as a config variable).

That way, it will adapt to whatever environment you're working on.


How do I disable the default translation feature for a custom field?

You can set the translation method  for each field individually

public static function supportedTranslationMethods(): array
{
    return
    [
         self::TRANSLATION_METHOD_NONE
    ];
 }


Craft or Twig filter for MD5 or SHA3 hash creation?

sounds like a simple plugin will do the trick for you. You will need to set up your main plugin class and a variable class.

Your variable class will look something like this:

<?php
namespace Craft;

class YourPluginNameVariable
{
    public function makeHash($string)
    {
        $hashed = md5($string);
        return $hashed;
    }
}

You can call this in your templates like this:

{{craft.yourpluginname.makeHash('my phrase here')}}

Hope this helps!


How should an index page be setup/defined in Craft?

Depending on the rest of your site structure, yes you can set these up as Singles.

Your other option is to use an Entry Type inside a 'pages' Structure, and in that template you list the first 6 categories in a defined Category Group (possibly selected in a dropdown, or through craft.request.segment() )

Documentation link on how Craft looks for index templates in case it's useful: https://docs.craftcms.com/v3/templates.html#index-templates.


You can read about how to use Relations in the docs. All relations such as (Tags) can be fetched via relatedTo parameter in your ElementsQuery

{% set tagId = craft.app.getRequest().getQueryParam('tagId') %}
{% set entries = craft
    .entries
    .section('faq')
    .relatedTo(tagId)
    .all()
%}

This assumes you include the parameter tagId when someone clicks on your Tag, and that represents the ID of your Tag

{% for tag in craft.tags.group(1).all() %}
    {{ tag.title }}
{% endfor %}


The only way I can think to do this is with a plugin that tracks the relation count, storing it as a custom field.

First create a new Number custom field called “Total Articles” (handle: totalArticles). Assign it to your Authors field layout.

Then create a new plugin. Put this in the primary plugin class’ init() method:

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

    if ($entry->getSection()->handle === 'articles') {
        // Update author relation counts
        foreach ($entry->relatedAuthor as $author) {
            $criteria = craft()->elements->getCriteria(ElementType::Entry);
            $criteria->section = 'articles';
            $criteria->relatedTo(array(
                'targetElement' => $author,
                'field' => 'relatedAuthor'
            ));
            $totalArticles = $criteria->total();

            craft()->db->createCommand()->update('content',
                array('field_totalArticles' => $totalArticles),
                array('elementId' => $author->id));
        }
});

Finally, from your template, you can fetch only the authors that have at least 2 articles like so:

{% set authors = craft.entries({
    section: 'authors',
    totalArticles: '>= 2',
    with: [
        'authorImage',
    ],
    limit: 18,
    order: 'authorSurname asc'
}) %}


Blank Screen on Site Search for some Search Terms

Are you doing any caching on this site? If you haven't tried already, clear all the caches and run the query again in  Utilities > Clear Caches

I did some test searches, and it appeared to be the exact search term that's failing rather than content that's returned by that search term, which makes me wonder about a corrupt cache.


Show larger images in control panel entries

The Asset Preview plugin is what you need. This allows you to toggle previews of assets by clicking on them and tapping the space bar. You can also use the arrow keys to navigate through all of the assets on a page.


How to create clean URLs for category strings?

First thing you'll need to do is set up a route that ensures anything for /products/category-name gets routed to the correct template. You can do this from the control panel or via craft/config/routes.php

If you do this in your routes.php file you'd need something like this:

return array(
    'products/(.*?)' => 'products/index',
);

Which is telling Craft that for any url that contains products/any-characters it should use the products/index template.

Then, on that template, grab the segment that is the category slug

{% set catSegment = craft.request.segment(2) %}

You'll then need to get the category that has that slug

{% set category = craft.categories.slug(catSegment).first() %}

You then have a category model you can work with and can use a craft entries tag with a category criteria using

{% set products = craft.entries.relatedTo(category).find() %}

Loop through products to output your products.


The section ID was incorrect - set correctly and this function works.


Any way to create new entry using certain entry type?

I assume you're talking about from the control panel?

If that's the case, then the answer is no.

But it sounds like you're asking for a way to maybe set a default entry type?

Regardless, this sounds more like a feature request.


The Element API plugin returns JSON, so you'll need to be specific about what you want to return for your categories – i.e. you can't return a CategoryModel (or an array of CategoryModels) in full directly from a Categories field.

The easiest option is to use array_map() like this:

'first' => $block->firstInstallment,
'second' => $block->secondInstallment,
'full' => $block->full,
'grant' => array_map(function (CategoryModel $category) {
    return [
        'id' => $category->id,
        'title' => $category->title,
    ];
}, $block->categoriesField->find()),

Of course, if your individual category has a lot of fields, you can always create an external function in your elementapi.php file and use that for the array_map call, instead of inlining the function (the external function needs to live above the return ['endpoints']... part):

function getCategoryData(CategoryModel $category)
{
    return [
        'id' => $category->id,
        'title' => $category->title,
        ...
    ];
}

...

'grant' => array_map('getCategoryData', $block->categoriesField->find()),

Also, there's the $category->getAttributes() method which can be handy if you want to return all stock attributes (i.e. id, dateUpdated etc – pretty much everything sans the title, for some reason):

function getCategoryData(CategoryModel $category)
{
    return array_merge($category->getAttributes(), [
        'title' => $category->title,
        'someCustomField' => $category->someCustomField,
    ];
}


Craft automatically includes the entry variable if the slug matches the url:

  If the URI matches an entry’s or category’s URI, the
  section’s/category group’s template will get loaded, and the matched
  element will be made available to the template via a pre-populated
  entry or category variable.

In your case contact-us gets matched automatically, but contact-us/thank-you does not. This means you have to set entry yourself.

Just add this to the top of your template:

{% if entry is not defined %}
    {% set entry = craft.entries.section('contact-us').first() %}
    {# Fetch single which has 'contact-us' as a handle #}
{% endif %}


Using static translations for the primary site / site.php being ignored

I think the error is to do with the fact that you are using backticks (slanted quote) instead of single/double quote marks.
Copy/paste the below and it should work for you
<?php

return [
  'UNIQUE_KEY_NAME' => 'This should now work',
];


No, you currently can't do that. But it's on The List! :)

See discussions in g+ here:

https://plus.google.com/110899911634334728373/posts/Q4Vi5d1y8Ry
https://plus.google.com/114292096121951987560/posts/PdXYBMxqbzb


Set cookie and redirect back to referral URL

Instead of relying on craft.request.getUrlReferrer() you could set a cookie containing the original URL before you redirect them to age verification page.

{% if getCookie('age') %}
    Page Content
{% else %}
    {{ setCookie('originalUrl', craft.request.url ) }}
    {% redirect "age" %}
{% endif %}

You can than use that cookie to redirect to the original link & destroy it again once you verified their age. Destroying it might not be entirely necessary as there's not duration specified so the cookie only lives for the current session.

{{ setCookie('age', '21', now | date_modify("+365 days").timestamp ) }}
{% set redirectUrl = getCookie('originalUrl') %}
{{ setCookie( 'originalUrl' ) }}
{% redirect redirectUrl %}


How would I setup my plugin to use a unique fieldlayout that is unique to the top level of the plugin?

You're bumping into this error because of a minor misunderstanding of how Pixel & Tonic are referencing their Element Types. The problem you have is with this line of code:

$fieldLayout->type = ElementType::MyElementType;

When P&T use that syntax, it's because they've already pre-defined all of their element types as enums. Open up the /app folder and take a look at this file to see what they've done:

  /craft/app/enums/ElementType.php

This allows them to use a syntax like ElementType::Asset.

You don't have that option (unless you create your own enum). What you would do instead, simply use a normal string to specify your element type:

$fieldLayout->type = 'MyPlugin_MyElementType';

This is the same string that you wrote when you defined the Model for your Element Type. It should be one of the first lines of code within your Model:

protected $elementType = 'MyPlugin_MyElementType';

Setting up enums is a different topic, but just go ahead and use the string and it should resolve that error for you!


Creating locale-specific entries from plugin

This is expected behaviour though, it's better (in my opinion) than leaving everything empty.

As Andrew said in his comment, you could by default disable all locales on this section so your entry wouldn't be published in multiple locales.

You can do this by going to the settings of your section:


Unable to connect to db via console with a custom config directory path

I ran into something very similar to this today. I have a custom path for plugins, as a result I could no longer run the plugin console commands because yiic.php is looking in the default path as specified by its defines. You need to let yiic.php know about your custom paths and unfortunately I don't think this is possible at the moment without hacking it.


Addresses are not Elements, so most import plugins will no support them as an import type.

You will need to create a plugin or script that imports the addresses into the commerce_addresses table. You could do this with a SQL query, but you could also use the Commerce address service like the example below.

Simply create an import.php file and place it in your public directory:

<?php
namespace Craft;

$craft = require '../craft/app/bootstrap.php';

$craft->plugins->loadPlugins();

$addressModel = new Commerce_AddressModel();

$addressModel->attention = '';
$addressModel->title = '';
$addressModel->firstName = 'John';
$addressModel->lastName = 'Doe';
$addressModel->address1 = '';
$addressModel->address2 = '';
$addressModel->city = '';
$addressModel->zipCode = '';
$addressModel->phone = '';
$addressModel->alternativePhone = '';
$addressModel->businessName = '';
$addressModel->businessTaxId = '';
$addressModel->businessId = '';
$addressModel->countryId = 1;
$addressModel->stateValue = 1; // can be (int) stateId or (string) state name

if(craft()->commerce_addresses->saveAddress($addressModel)){
    echo "Address Saved";
}else{
    $errors = $addressModel->getAllErrors();
    echo 'Errors
';
    foreach ($errors as $error) {
        echo 'Error: '.$error;
        echo '
';
    }
};

$craft->end();

The above code will insert one Address.

You will then want to assign this address to a customer/user, so you will need to do the following:

1) Create a customer record in the commerce_customers table with the userId and email values set to that of the user.

2) Insert a record into the commerce_customers_addresses table with the customerId and addressId for each of the addresses belonging to that customer.

Steps above can be done directly as SQL inserts into the tables mentioned.

This will make the address available for selection on checkout.


SEOmatic plugin override global title in individual template

Are you using the SEOMatic Meta fieldType?

What I do is create a field of this field type and assign it to the entry type you're dealing with. Within this field, there are all sorts of values you can override. For instance, you can point the SEO title field to one of your other fields via a dropdown, or you can manually type in a new SEO title just for this particular entry.


Something like this should do it:

{% set entries = craft.entries.section('news').relatedTo({
    targetElement: currentUser,
    field: 'customUserField'
}).find() %}

More on the relatedTo method here: https://craftcms.com/docs/relations


Custom Token Authentication with Craft 3 Login Form

The submit action is the actionInput input {{ actionInput('users/login') }}.
This will call the login method of the src/controllers/UsersController and perform the action.

You may also take a look at User Element & Events where you can listen on various user events like EVENT_BEFORE_VALIDATE, EVENT_BEFORE_AUTHENTICATE etc.


Use function provided by plugin only if plugin is installed and enabled

you can check if the plugin is installed and enabled with:

{% if craft.app.plugins.isPluginEnabled('assetrev') %}
  {% set fileName = rev(file) %}
{% else %}
  {% set fileName = file %}
{% endif %}

you won't need the extra check craft.app.plugins.isPluginInstalled('assetrev') then.

isPluginEnabled():

  Returns whether a given plugin is installed and enabled.