How to get an entry url from EVENT_AFTER_SAVE_ELEMENT callback? In my plugin I am registering a callback for Elements::EVENT_AFTER_SAVE_ELEMENT event. Previously, in Craft2, I could access the URL of the saved entry from the $event parameter passed into the callback, like so: $event->params['entry']->getUrl().

However I can't figure out how to get a reference to the entry in the Event model in Craft 3. If I var_dump($event) I can see the data I want nested deep inside a private property which I cannot access.

How do I access the entry data from the event in Craft 3?

Check out the definition of the ElementEvent that you're passed:

class ElementEvent extends Event
{
    // Properties
    // =========================================================================

    /**
     * @var ElementInterface|null The element model associated with the event.
     */
    public $element;

    /**
     * @var bool Whether the element is brand new
     */
    public $isNew = false;
}

So you can access the element (in your case, presumably an Entry) via:

$event->element

Make sure to check for null, and depending on how you set up the event listener, that the element is of the type of you're looking for.

For instance, if you want only listen to all elements that are saved, you'd do:

    Event::on(
        Elements::class,
        Elements::EVENT_AFTER_SAVE_ELEMENT,
        function (ElementEvent $event) {
            Craft::debug(
                'Elements::EVENT_AFTER_SAVE_ELEMENT',
                __METHOD__
            );
        }
    );

...but if you only care about Entry elements, you'd do:

    Event::on(
        Entry::class,
        Entry::EVENT_AFTER_SAVE,
        function (ModelEvent $event) {
            Craft::debug(
                'Entry::EVENT_AFTER_SAVE',
                __METHOD__
            );
        }
    );


Pulling assets into a plugin I'm trying to auto-post from my blog to Facebook using Buffer and this plugin (https://straightupcraft.com/craft-plugins/buffer). The addon requires me to create a plugin to do the actual posting to Buffer. This is my first foray into plugins at all. I used his example and got something that works.

However, the question I have is somewhat general. How do I pull an asset from an entry that has been saved to be able to post to the plugin?

This is the relevant portion of the plugin:

$picture = craft()->request->getUrl($entry->blogImage);

craft()->buffer_utils->queueBufferUpdate($updateString, true, $link, $picture, $thumbnail);

Obviously, my asset field name is blogImage.

Also, and let me know if I need to create a new question for this, how does onBeforeSaveEntry affect scheduled content? Does/will the plugin run when it's actually saved or when it becomes "live"? If so, is there a workaround for that?

Thanks.

edit: I did reach out directly to the developer but have not had any luck yet and was hoping the question was general enough that someone else might be able to help!

To get the URL of an asset in a plugin, you use a similar technique as you do in twig, so this will fetch the URL of the first image in the blogImage field:

$picture = $entry->blogImage->first()->url;

To answer you second question, onBeforeSaveEntry is run just before the entry is actually saved, not just before it is published live on the site if it has been saved with a post date in the future.

Craft doesn't fire any events just before an entry becomes 'live' on the site, so if you want the post to Buffer to go out at the same time as the entry goes live using this technique, you will need to actually create and save the entry when you want to publish it live on your site.


Hide section on "Entries" tab Is there a way to hide a section from the Entries tab based on user permissions? Whether it means creating a user permission in a plugin, or hiding the section selection tab from Entries altogether.

I have a channel that users with a certain permission can create entries in using a front-end form. Once created, I don't want the user to see the entry in the CP or to have the ability to edit it.

I'd like to still allow them to see other entries in the "All entries" tab, so my original plan to hide these sections through CPCSS doesn't work. Any other ideas?

There’s no way to give a user group permission to create entries but not see those entries they created in the CP.

The only way to achieve what you want would be to write a plugin that provides its own “save-entry” controller action, which allows users to create the entries without actually having the permission. The Guest Entries plugin would be a good starting point - it has a GuestEntriesController with an actionSaveEntry() method that behaves very similar to Craft’s built-in EntriesController::actionSaveEntry(), but it skips the normal permission-based authorization logic.

In your case you might still want some level of authorization. For example, you can verify that there’s a currently logged-in user, and that they belong to a certain group. If that’s the case you’ll want to not add this line:

protected $allowAnonymous = true;

And at the top of your actionSaveEntry() method, add this:

$user = craft()->userSession->getUser();

if (!$user->isInGroup('authors'))
{
    throw new HttpException(403, Craft::t('This action may only be performed by authors.'));
}


Get Entries from Every Site How do I pull in entries from every site? I can't even seem to pass more than one argument to the .siteId parameter:

{% set entries = craft.entries({
    section: 'resources',
    siteId: [1,2,3],
}).all %}

That gives me the error:

  Argument 2 passed to craft\services\Elements::getPlaceholderElement()
  must be of the type integer, array given

I also tried:

{% set entries = craft.entries({
    section: 'resources',
    siteId: craft.app.sites.allSiteIds,
}).all %}

But got the same error.

Per current conversation on Github, this isn’t possible. https://github.com/craftcms/cms/issues/2854


Using field types to override meta defaults I was wondering if someone could help me find a solution to this. I didn't see it in the docs. Perhaps I missed it...

I created an entry type with the field type Meta: Basic. I would like to use this to override the meta defaults at the entry level. It doesn't appear to do it on it's own and accessing the content via entry.metaBasic.description doesn't work either. What am I doing wrong? Thanks in advance.

To override the Default meta data with your field type the only addition you need in your code is to pass the entry.id to your craft.sproutSeo.meta tag:

{% do craft.sproutSeo.meta({
    id: entry.id,
    default: 'default',
    title: entry.title,
    description: entry.body|striptags|slice(0, 160)
}) %}

Once you identify the entry.id Sprout SEO will handle the rest, prioritizing any values you have in your field types above any values in your Defaults or Code Overrides.


Is there a way to know if a discount is going to be applied on a product? I have set up a number of discounts using Craft Commerce. Those discounts apply to specific groups of users and types of products.

Is there a way to know inside the template, if a discount is going to be applied without checking the product type or user group of the current user?

Discounts can only be determined if the item is added to the cart. This is what separates a discount from a sale.

A discount is actually not matched with the product but the line item as it sits on the order (with all of its context like the order's customer, etc)

You can determine if something is on sale with variant.onSale returning true or false.


Craft update doesn't update I am trying to update Craft, but when I do, it says update complete, but still shows that there is an update available. It stays on version 2.5.2759 but never updates to the latest 2.6.2776 version. I am running PHP 5.5 and Craft is installed locally.

Any ideas how I can diagnose what is going on?

The update process gets extensively logged in craft/storage/runtime/logs, so that's the place to go to start diagnosing.  You can search for [error] once you find where the update logs start and see if it reveals anything useful.

If nothing jumps out at you, you can contact support@craftcms.com and they can help diagnose the issue.


MatrixBlockModel error - "Call to a member function on a non-object" I'm having some trouble trying to write a plugin. I'm trying to create a simple fieldtype that I'm going to use inside a matrix block.
So far the public function getInputHtml of my fieldtype class, contains only:

var_dump($this->element)

And it shows me, as expected:

object(Craft\MatrixBlockModel)#1121 (25){["elementType":protected]=&gt; string(11) "MatrixBlock" [.......]

The problem is that, as I try to change the previous

var_dump($this->element)

with a

var_dump($this->element->getOwner())

(or any other method/property of the MatrixBlockModel class), I obtain:

  "Call to a member function getOwner() on a non-object"

Any suggestion? Could it have something to do with the magic methods (maybe __call) inherited by CComponent class?

Matrix initializes its blocks’ field types multiple times – once for each existing block in the field, and one last time to get the initial input HTML that should be used when new blocks are added.

For existing blocks, $this->element will be set on the field types, referring back to the existing MatrixBlockModel objects representing each of those blocks.

That won’t be the case the time that your field type is just telling Matrix what the initial input HTML should be, however, since no corresponding Matrix block exists yet.

When you call this:

var_dump($this->element);

it’s not giving you any errors because $this->element will just be null when there is no element set, and there’s nothing wrong with dumping a null variable.

But when you call this;

var_dump($this->element->getOwner())

now you’re trying to access a method on $this->element, which won’t necessarily be set, and that’s when you’re getting that exception.

So what you need to do is ensure that $this->element is actually set before trying to access getOwner():

if (isset($this->element))
{
    $owner = $this->element->getOwner();

    if ($owner)
    {
        // ...
    }
}

Note that I’m also not assuming that getOwner() will actually return anything, because that’s not a certainty either. For example if you create/save a new entry but there are validation errors, when the Edit Entry page reloads, you will have MatrixBlockModel objects for each of the blocks you had created, which $this->element will point to, but they won’t actually have IDs nor an owner yet.


How do I use divisibleby() in a for loop to display two columns? I try to write a row in which there are two columns:

{# and so on and so on #}

Now maybe there is only one block_txt div at the end so I try to wrap the row tag in a devisibleby conditional to only write the row tag every second time, or at the end.
It looks like this:

{% for entry in entriesInYear %}
   {% if loop.index is divisibleby(2) or loop.first %}
{% endif %}

This gets repeated n times

   {% if loop.index is divisibleby(2) or loop.last  %}
{% endif %}
{% endfor %}

But that doesn't work the way I want. Every third block_txt isn't wrapped in a row. How do I have to math this? Or is there a better way to write the whole piece?

Instead of using the divisibleby-function you can use the batch-filter:

{% for row in entriesInYear|batch(2) %}

    {% for entry in row %}

    {% endfor %}

{% endfor %}

If you have 3 entries in entriesInYear this code would output:


How can I create a status message of X of TOTAL pages under a parent? I have a Structure section with an ordered number of entries under a parent. On each entry I would like to add a status message of the user's current progress... i.e. You are on page 1 of 5 pages.

The total was easy...

{% set total = entry.getParent(entry).getDescendants().count() %}

How do I get the current page (child) number within the total number of children.

Thanks!

I assuming the pages are one level down from the parent?

Parent
  | Child (1)
  | Child (2)
  | ... etc

You can do this:

{% set topLevel =  entry.parent %}
{% set totalPages = topLevel.getDescendants().count() %}
{% set entryIds = topLevel.getDescendants()|group('id')  %}
{% set currentPageNumber = (entryIds|keys)|indexOf(entry.id) + 1 %}

{{currentPageNumber }} of {{totalPages}}

Basically we're making an array (list) out of just the entry IDs by grabbing the descendants from the parent. Then we use Craft's group function to give us an array, grouped by key (in this case the ID). Since we know the current page's ID, we can find it in the array and return its position. Since arrays are indexed starting with 0, we just add 1 to it.


Get all Categories with getGroupById in Element API plugin - Craft 3 I have an endpoint created and I am getting the groupID but I am unable to get all the categories associated with the group.

This is what I have right now:

$categoriesGroup = Craft::$app->categories->getGroupById($catId);

I can't seem to get an array of entries from that.


Sorting SuperTable Field with SuperSort? I'm trying to use supersort to sort my entries based on date values in a supertable field.

This is what I have so far but it's not working.

{% set artists = craft.entries.section('artists') %}
{% set entries = artists | supersort('sortAs', '{{ tourDates.tourDate }}') %}

tourDates is the supertable handle tourDate is the date field in the table. There can be multiple date entries in one table so it would need to bring them out in order as well.

I'm not sure this is even possible.

I think you need to add 'object' to your syntax if you're using {{ }}:

{{ object.tourDates.tourDate }}

Else it's { tourDates.tourDate } I believe.

See the plugins docs under Advanced sorting.


How do I find the category an entry belongs to? I have a channel with entries which have a category field which is required.
When the entries are listed on a page how do I find the category that it belongs to?

{% for entry in entries %}
    {{ entry.title }}
{% endfor %}

Code so far is above.

The category has a background color field which I want to apply to the .

If I'm following you, you've got a category group setup with a color field on its field layout.

Then you've got a category field setup with it's source set to that category group and in an entry, you want to get to the color field on the category group.

{% for entry in entries %}

    {# Grab the first category #}
    {% set category = entry.categoryFieldHandle.first() %}

    {#
        Or if there are multiple categories...
        set category = entry.categoryFieldHandle.find()
        And loop through to find the one you want
    #}

    {{ entry.title }}
{% endfor %}


Check in header file if lightswitch field is on For a menu I have to check if a lightswitch field is on or not. The menu is in an extra header file. I've tried:

{% if craft.entries.section('aboutus').lightswitch_field %}style="display: none;"{% else %} ... {% endif %}

but this always jumps into the else part.

Try:

if craft.entries.section('aboutus').lightswitch_field('1')|length

If you want to check if it is "off" use:

if craft.entries.section('aboutus').lightswitch_field('not 1')|length


Saving Entry with Category field I am stuck on saving entry with a category field.
The error message I get is about not being able to create/update the entry in the relations table.

$accomodationTypecategory = ['title'=>'Hotel']

$entry = new EntryModel();
$entry->sectionId = 3;
$entry->typeId = 3;
$entry->authorId = 1;
$entry->enabled = true;
$entry->setContent(
    $entry->getContent()->setAttributes([
        'title' => 'Test Entry',
        'body' => "Testing",
        'address'=>"101 Silver Avenue",
        'phone'=>'0209900292092',
        'websiteAddress'=>'www.example.com',
        'towns'=>'Newy',
        'accommodationType'=>$accomodationTypecategory
    ]);

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

Any help will be appreciated.

To set a related category (or any other kind of element) you will want to pass an array of categoryIds (elementIds) — even if, as in this case, there is only one category or element. You can either set the ID as a static value if it's predefined or dynamically look it up based on the title, slug or any other unique element attribute.

$criteria = craft()->elements->getCriteria(ElementType::Category);
$criteria->title = 'Hotel';
$accomodationTypeCategory = craft()->elements->findElements($criteria);

$entry = new EntryModel();
$entry->sectionId = 3;
$entry->typeId = 3;
$entry->authorId = 1;
$entry->enabled = true;
$entry->getContent()->setAttributes(array(
    'title'             => 'Test Entry',
    'body'              => 'Testing',
    'address'           => '101 Silver Avenue',
    'phone'             => '0209900292092',
    'websiteAddress'    => 'www.example.com',
    'towns'             => 'Newy',
    'accommodationType' => array(
        $accomodationTypeCategory[0]->id
    )
);
craft()->entries->saveEntry($entry);


How to manage multiple categories and entry url formats I have a setup in Craft 2 like below:

Section: products
Url format: flowers/{productCategory.last.uri}/{slug}

Categories:
cat1 = Bouquets
cat2 = Valentines days
Url format: flowers/{slug}

The problem headache arises when I want to get the entry URL within a category template. It always gets the last category of the entry due to the URL format. So once valentines day is added as a second category then a normal bouquet entry URL goes from this:

/flowers/bouquets/entry-slug

to

/flowers/valentines-day/entry-slug

I solved this partly by making my bouquet URL out of the URL path:

            {% for entry in entries %}
                {% set prodUrl = 'flowers/'~ seg2~ '/'~entry.slug %}
                 <a href="{{ baseUrl }}{{ prodUrl }}" >

However, the entry template now doesn't have the entry model.

How do other people solve this multiple categories for the same content type issue?

I can think of a couple possible solutions here:

1. Rethink your url structure
You could always remove the category segment from the url. Maybe create a field for the main category and then another field for all the categories, and use the main category field for your URL. Or you could fetch the first productCategory instead of the last one, so there's less chance of it changing. In my opinion you're going to have a lot of SEO issues if your url changes whenever you add a new productCategory, not to mention broken links and all sorts of other headaches.

2. Do some fancy stuff with routes and entry queries
I think technically you could set up a route like flowers/{productCategory}/{slug} and then in your template do an entry query for an entry with that slug. But probably better to think over #1 and find a cleaner solution.


Output array to Plugin::log Just wondering if its possible to output an array to the Plugin::log call? Would be really handy to see if an error occurs, what a data object's values are!

Tried the following:

Plugin::log(array('test')), LogLevel::Error);
Plugin::log(json_decode(array('test')), LogLevel::Error);
Plugin::log(var_dump(array('test')), LogLevel::Error);
Plugin::log(print_r(array('test')), LogLevel::Error);
Plugin::log(\CVarDumper::dump(array('test')), LogLevel::Error);

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

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


Dynamically populating select input fields using jquery $.load and twig template EDIT: the below code now works!

I have two select inputs, the choice of 1 should populate the second. I have an external twig file (data.twig) (MAKE SURE TO PUT THIS IN YOUR TEMPLATES FOLDER) that loads the options of the second field.

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

{% set brands = allBrands.all() %}

test form

    <select id="first-choice" class="select-1">
        <option selected value="base">Please Select</option>
        {% for entry in brands %}
        <option value="{{ entry.brandName }}">{{ entry.brandName }}</option>
        {% endfor %}
    </select>

    <select id="second-choice" class="select-1">
        <option>Please choose from above</option>
    </select>

Then for the javascript:

$(function() {

        $("#first-choice").change(function() {
          $("#second-choice").load("{{ siteUrl }}data.twig?brand=" + $("#first-choice").val());
        });

    });

And lastly the data.twig:

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

{% set allModels = craft.entries()
                .section('brands')
                .brandName(brand)
                %}
{% set models = allModels.all() %}
{% for entry in models %}
<option>{{ entry.modelName }}</option>
<option>testing</option>
{% endfor %}

Your code looks fine and worked for me when testing locally. However it could be failing due to the fact that you're not url-encoding the parameter before you send the request. If the values contain spaces or other special characters, for example, this would make it fail. To fix that issue, try using encodeURI() like this:

$("#second-choice").load("{{ distUrl }}data.twig?brand=" + encodeURI($("#first-choice").val()));

This works for me when testing with values that contain spaces at least.


Migrations running on their own causing site down I'm a bit stumped with this one and wonder if anyone else has come across it.

I've a site live which is using the 'Formerly' plugin amongst others, since a recent update the site has gone offline twice in the last week do to the formerly plugin needing to make changes to the database.

I didn't think this could happen on it's own? It's like the plugins migration wants to run on it's own at weird intervals.

Not sure how to debug this, anyone else had this issue?

Plugin Migrations run as soon as Yii finds a new file. So as soon as there is a new file in your migration folder Craft starts to migrate it the next time someone triggers Craft tasks (usually by entering the CP). When you hit the Update button in your CP there could be that chance that a plugin makes an update -> pulls those migration files.

What do you mean with "how to debug this"?

If you want to remove the task, you can clear the task table and get rid of it. You can take a look at the plugins migration folder and see if there are any new files.


Why are some entry detail views empty in the control panel? I can't seem to edit entry details all of a sudden: in this Products section (and only this one section), the page title and "Current Version" button will render, but the rest of the page is missing.

The only clue is this line from Craft's log:

  [31-Jul-2014 19:07:36 UTC] PHP Fatal error: Maximum function nesting level of '100' reached, aborting! in /Users/gob/projects/gobias/craft/app/vendor/twig/twig/lib/Twig/Node.php on line 140

I've loaded earlier MySQL backups, restarted MAMP Pro (PHP 5.5.10), cleared Craft's caches, tried different browsers and machines, and the problem persists.

That error isn't a Craft or PHP error, it's coming from older versions of xDebug.

It can happen on more complicated pages (lots of fields, tabs, etc.), but you can get around it by adjusting the xdebug.max_nesting_level to something higher than the default 100 or to upgrade xDebug to 2.3+, which has changed to the default value to 256.

Note that you don't have to have an active debug session going on in order to run into this, you just have to have the xDebug extension installed.


Getting all the values out of a field as array of values I have a multi-select field in my work section

I want to get the values either with the Element api as json or an array of simple values in my template.

$element->getFieldValue('handle') or it's Twig equivalent element.handle contains an Object of type MultiOptionsFieldData you can get all possible values via itsgetOptions()` function

Twig

{{ dump(entry.fieldHandle.getOptions()) }}

PHP

$options = $element->getFieldValue('handle')->getOptions();


How do I output the locale’s name? When I output {{ craft.locale }} in my template, I get the current locale’s ID (e.g. “en”) rather than its name (e.g. “English”).

How do I get the locale’s name?

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

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

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

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

{{ locale.nativeName }}

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

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


Change php.ini to max execution 120 I found the php.ini file, but I don't see where to change max execution to 120.  Thank you for your support.

Open the php.ini file in your favorite text editor.
Search for max_execution_time. It'll probably be set to something like 30 or 60.
Change it to 120 and save the file.
You'll likely need to restart your web server before the change takes affect.


Does Craft CMS support MySQL over SSL? Does Craft CMS support MySQL over SSL?

Thanks!

Update:

As of the next Craft 2.6 release (post 2.6.2945), Craft has exposed an attributes database config setting that you can pass arbitrary PDO attribute key => value pairs into.

So, assuming your MySQL box is setup properly to use SSL and assuming the database user that Craft is using to connect to the box can connect over SSL, then you can do something like this to enable Craft to talk to MySQL over SSL:

'attributes' => array(
     PDO::MYSQL_ATTR_SSL_KEY    => '/path/to/my/client-key.pem',
     PDO::MYSQL_ATTR_SSL_CERT   => '/path/to/my/client-cert.pem',
     PDO::MYSQL_ATTR_SSL_CA     => '/path/to/my/ca-cert.pem',
 ),

Original:

In Craft 2.x, this isn't currently possible.  Craft 3, however, will expose the necessary client side configs so that if your MySQL box has an SSL cert installed and supports SSL, then you can configure Craft to connect via SSL.


Add active class and territory name to language switcher I've worked up this code with big help from @carlcs.
I want to set up a class if current locale is turned on.

Firstly, I tried the easiest way by putting {{ current ? 'my-class' }} into li.
Secondly, I tried to set variable for current locale.

I've end up by struggling to answer my question, Why all locales are turned on?

{# Language switcher #}
{% set locale = craft.i18n.getCurrentLocale() %}

{# Configure site locales #}
{% set locales = ['en', 'en_gb'] %}

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

{# Give locales class or text #}
{% if locale == 'en' %}
     {% set territoryCode = 'world' %}
     {% set active = 'uk-active' %}
{% endif %}

{% if locale == 'en_gb' %}
     {% set territoryCode = 'uk' %}
     {% set active = 'uk-active' %}
{% endif %}

{# This is the current locale #}
{{ territoryCode|upper }}

{% set locales = ['en_001', 'en_gb'] %}
{% for locale in locales %}
{% set subTags = locale|split('_') %}
{% set territory = subTags|length > 1 ?craft.i18n.getLocaleData(craft.locale).getTerritory(subTags|last) : '' %}
{% set language = craft.i18n.getLocaleById(locale).name %}
{% set language = language ?: craft.i18n.getLocaleById(subTags|first).name %}
{% set language = language|replace("/- #{territory}$/", '') %}

       {% if territory and language %}
            {{ territory }} ({{ language }})
       {% endif %}

{% endfor %}

Update

{% set locales = ['en_001', 'en_gb'] %}

 {% for locale in locales %}

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

 {% set subTags = locale|split('_') %}
 {% set territory = subTags|length > 1 ? craft.i18n.getLocaleData(craft.locale).getTerritory(subTags|last) : '' %}
 {% set language = craft.i18n.getLocaleById(locale).name %}
 {% set language = language ?: craft.i18n.getLocaleById(subTags|first).name %}
 {% set language = language|replace("/- #{territory}$/", '') %}

        {% if territory and language %}
            {{ territory }} ({{ language }})
        {% endif %}

 {% endfor %}

The comparison is meant to be used within the for loop that loops your array of locales. And you can of course only compare the current locale tag craft.locale to real locale tags and not with fake ones like 'en_001' that Craft doesn't know about.

{% set locales = ['en', 'en_gb'] %}

{% for locale in locales %}
    {% set current = (locale == craft.locale) ? true %}
{% endfor %}

So you need to find a way to map real locales to your fake ones! The real ones for your craft.locale comparison and the fake ones to get your territories. But then there would be no need to compose fake ones to start with and you would simply map the real locales you installed and use in Craft to the territory names or territory codes for your output string. So let's do this.

{% set locales = {
    'en':    '001',
    'en_gb': 'gb',
    'hu':    'sk',
    'de':    'sk',
} %}

{% for locale, territory in locales %}

    {% set current = (locale == craft.locale) ? true %}

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

    {% if territory and language %}
        <li class="{{ current ? 'myCurrentLocale'}}">
            Territory: {{ territory }},
            Language: {{ language }}
        </li>
    {% endif %}

{% endfor %}


500 error on installation since version 2.3 I have tried everything to install Craft on my server, and I have not been able to do it. I have done this a few times before without any issues, but since version 2.3 was released, I can't access the admin panel to start the installation.

I have followed all the steps in the documentation, I have created new DB, new domains.... nothing! I get a 500 error every time I want to access the admin area.

What am I missing?

2014/12/15 19:21:19 [error] [exception.Craft\HttpException.404] exception     'Craft\HttpException' in       /home/content/33/10789233/html/links/craft/app/etc/web/WebApp.php:737
Stack trace:
#0 /home/content/33/10789233/html/links/craft/app/etc/web/WebApp.php(176): Craft\WebApp->_processInstallRequest()
#1 /home/content/33/10789233/html/links/craft/app/framework/base/CApplication.php(180): Craft\WebApp->processRequest()
#2 /home/content/33/10789233/html/links/craft/app/index.php(62): CApplication->run()
#3 /home/content/33/10789233/html/links/public/index.php(19):      require_once('/home/content/3...')
#4 {main}
REQUEST_URI=/
---
2014/12/15 19:21:19 [error] [application]
2014/12/15 19:21:21 [error] [application] Unable to determine if a script name         redirect is in place on the server: Server error response
[status code] 500
[reason phrase] Internal Server Error
[url] http://website.com/testScriptNameRedirect

I might be shooting in the sky, but make sure that in your in your .htaccess you have

  RewriteBase /

after

  RewriteEngine On


Smart Map Lat+Lng is present but no pin on map My map isn't showing all of the markers that it should. I am querying a user group to return the locations as follows:

{% set locations = craft.users.group('fullMembership') %} {{ craft.smartMap.map(locations, options) }}

FYI There are around 400 users in this group and only a small amount of them have logged in and set their Map Pin.

Each user in this group has a profile page; Those user who have located their address  all show their map pin on their profile. However the members Directory index map is incomplete, some pins are missing.

As Craft defaults to only returning 100 elements, setting the limit(null) parameter to the query fixed this issue.

{% set locations = craft.users.group('fullMembership').limit(null) %}


Change position of entry types in a structure I was wondering if there's a way to change the position of elements in an entry type structure. I want to change the positions of the elements when a user logs in, so I'll write it in a plugin.

Any Ideas?

This did the trick:

 craft()->sections->reorderEntryTypes($entryTypeIds);

Where $entryTypeIds is an array with all the id's in the correct order


Efficient way of looping through a large amount of users? Hi I have a plugin that loops through users to find out their interests. Counts the number of interests in total for each interest and displays this in a widget on the dashboard with the interest name and amount of users with that interest. The code I have works but fails with a max execution time and only pulls out minimal results for each interest. Is there a way to do this more efficiently so the script does not timeout. This is what I have so far but I'm sure looping through 20k+ users and checking each interest field to see if the category id is in it is highly inefficient. Cheers.

public function getInterestRank()
{
    $criteria = craft()->elements->getCriteria(ElementType::Category);
    $criteria->group = 'interestTags';
    $category = $criteria->find();

    //Get all users
    $user_criteria = craft()->elements->getCriteria(ElementType::User);
    $users = $user_criteria->find();

    $interestArray = array();

    foreach($category as $interest)
    {
        $title = $interest['title'];
        $count = 0;

        foreach($users as $user)
        {
            if($user['interests']) {
                if(in_array($interest['id'], $user['interests']))
                {
                    $count = $count+1;
                }
            }
        }
        $interestArray[$title] = $count;
    }

    arsort($interestArray);
    return ($interestArray);
}

You could just setup a criteria model in your “categories” for-loop, prepared to query for the users related to that category. And then use the total() method to get the count.

foreach($category as $interest) {
    $user_criteria = craft()->elements->getCriteria(ElementType::User);
    $user_criteria->relatedTo = $interest->id;
    $count = $user_criteria->total();

    $interestArray[$interest->title] = $count;
}

Using the total() method is a lot faster than find(), the underlaying SQL which is necessary to get the amount of rows performs better and Craft also doesn’t have to populate the Entry models with all the data.

(Not sure why @LukePearce deleted his answer, where he basically suggested to do the same thing.)


How do I know if a plugin supports Craft 3.1's project config? Craft version 3.1 introduced the project config file.

The documentation mentions "plugins may not support it yet:"

  Any plugins that are storing configuration settings outside of their main plugin settings will need to be updated to support the project config. So there may still be some cases where changes need to be manually made on each environment.

Is there any way to know if a plugin for Craft 3 supports project config files?

The best I could find was searching thru a plugin's changelog in the Craft Plugin Store for something like "Added support for Craft 3.1 project config."

Super Table version 2.1.1:

Added support for Craft 3.1 project config.

Redactor version 2.2.0:

Redactor for Craft CMS now requires Craft 3.1.
Improved Project Config compatibility.


Part of a website only accessible to users Is it possible to restrict a part of a website to craft user-groups?

For instance if I want show an internal Blog to members-only.

And is it possible to moderate user registrations? So when somebody registers an Admin has to approve it first?

It is! You can use the requirePermission tag:

{% requirePermission "yourPermission" %}

See the full documentation here. Keep in mind this list as built in permissions but you can also add custom permissions through a plugin should you require it.

As far the second question, I'm not 100% sure but I believe you can set "enabled" to "false" when creating a registration form. See further details here.

Update: You can also use isInGroup


Dropdown that shows all months and when selected displays all entries from that month This snippet displays every post by postDate, which lists a bunch of “October 2015”. I am trying to filter by month/year, so only one “October 2015” shows then one “November 2015”, then one “December 2015” so on and so forth. So choosing the month, shows all posts from that month.

by date

    <select name="blog-date" id="blog-date" onchange="window.location.href=this.value;">
        <option value="/blog">All Time</option>
        {% cache %}
        {% nav entry in craft.entries({ group: 'blog', order: 'postDate desc', limit: null }) %}
            <option value="{{ entry.postDate | date('F-Y') }}"
                {% if craft.request.getLastSegment() == entry.postDate %}selected{% endif %}>
                {{ entry.postDate | title | date('F Y') }}
            </option>
        {% endnav %}
        {% endcache %}
    </select>

The following three resources should be substantial enough to find a solution:

Linking and showing archive by month
Craft Docs: Grouping by year and then month
Need to access year/month variable when grouping entries by date


Remove $_SERVER and DB Queries from logs in 3.4+ How can we disable Craft from logging MySQL queries and $_SERVER object into the logs?
For our team, this creates additional noise that's not needed for us to debug issues.
Thanks :)

If you disable devMode in config/general.php, that information won't be logged.


How to handle form submissions? So I am coming from WordPress and typically I would typically handle a post by either hooking into the wp_post action and access the $_POST request that way. Now I believe Craft is built on Yii which is an MVC framework but I cannot find any documentation showing how to handle post requests?

Any help or can you point me in the right direction?

Doing it through a plugin would be the easiest way.

https://docs.craftcms.com/v3/extend/plugin-guide.html

Your plugin would have a controller that the form would post to, then you'd grab the data from POST and do whatever you want with it.

A good example of this you can look at is the Guest Entries plugin, that allows "anonymous" front-end entry submissions.


Member uploaded images I'm considering using Craft for a new site. One requirement will be allowing members to upload and manage images. With Craft, can I set a size requirement for member uploaded images? So for example, if I only wanted to allow 400x400 image size to be uploaded, could I lock it down so that any image smaller or larger will just give an error?

If that's not possible, is there a way to resize/crop a large image down to the correct size?

You can ad {author.username} to the file upload field, that way their files will always be in the folder of the user.

With assets you can define scale sizes which works way better then forcing a fixed size. It doesn't stop someone from uploading a 36 Mp image though. As far as I know it's impossible to check the canvas size before upload.


Breadcrumbs for Craft 3 How do you make breadcrumbs in your Twig templates for Craft 3?

Unfortunately I found examples only for Craft 2

When it comes to creating breadcrumbs, I can only offer advice when doing so within a structure.

Craft 3 still has .ancestors available on an entry so you can do:

{% set breadcrumbs = entry.ancestors.all() %}

Then check the length and loop through the ancestors for the structure entry.

{% if breadcrumbs|length %}

Home

        {% for crumb in breadcrumbs %}

{{ crumb.title }}

        {% endfor %}

{{ entry.title }}

{% endif %}

Then just add a little CSS to style as you choose.

This would use &raquo; between each entry.

Home » First Article » Another Article » Grandchild Article


No index.php file created during install using composer This is on Centos 7.5 using a vmware local vm

Installed Apache, MariaDB 10.2, PHP 7.1 (Remi) in that order

Logged in as root, no sudo or su

Installed composer 1.6.5 without issue

  cd /var/www/html
  composer create-project craftcms/craft .
  ./craft setup
  No errors or warnings after confirming "yes" to "Install Craft now?"

I had the same problem trying to install from the archive manually but I figured I might have done something wrong so I set up a clean new LAMP VM and used only composer. I appreciate any help.

Directory contents below

  [root@localhost html]# ll
  total 128
  -rw-r--r--  1 root root    387 Jul 17 13:37 composer.json
  -rw-r--r--  1 root root 100025 Jul 26 15:02 composer.lock
  drwxr-xr-x  3 root root     88 Jul 17 13:37 config/
  -rwxr-xr-x  1 root root    577 Jul 17 13:37 craft*
  -rw-r--r--  1 root root    330 Jul 17 13:37 craft.bat
  -rw-r--r--  1 root root    926 Jul 26 15:06 .env
  -rw-r--r--  1 root root    875 Jul 17 13:37 .env.example
  -rw-r--r--  1 root root     31 Jul 17 13:37 .gitignore
  drwxr-xr-x  2 root root     24 Jul 17 13:37 modules/
  drwxr-xr-x  4 root root     51 Jul 26 15:02 storage/
  drwxr-xr-x  2 root root     40 Jul 17 13:37 templates/
  drwxr-xr-x 28 root root   4096 Jul 26 15:02 vendor/
  drwxr-xr-x  3 root root     77 Jul 17 13:37 web/

Your index.php file should be found under the web directory. All of the other files and folders installed by composer are considered to be above the root which is recommended for security reasons.

Place all of your css, js, images, etc into the web folder and create your twig files in the templates folder and you shouldn't need to edit your index.php file, but web is essentially where it lives. This folder can be renamed to public, httpdocs, or anything you wish. It will be used by your set up as the public root of the domain. I hope that helps.


What's the difference between CraftSessionId and a normal PHP session? Doing some testing, and stumbled across the "CraftSessionId" cookie...

What's the difference between CraftSessionId and a normal PHP session? Is there any difference at all? What's the best way to refer to the current session?

They are one in the same.

Craft simply renames it to "CraftSessionId" rather than the default "PHPSESSIONID".

The only additional things we do to it is set the "httpOnly" flag so that JavaScript can't read it and change the place it is saved to by default (varies per server) to craft/storage/runtime/sessions.

You can see that in action in HttpSessionService, which extends Yii's CHttpSession, which is a convenient wrapper for PHP's session functionality.


Can I move existing tags, which are currently in a global tag group, to new the new tag groups I've set up? I've set up new tag groups to help organise the c300b tags we have set up. How do I move the existing tags, which are already in use, to the new tag groups?

There is no way to do this natively in Craft through the control panel.

You could either write quick plugin that programmatically moved the existing tags to new tag groups or write some custom SQL that did it directly against the database.

For the latter, it should be as simple as updating the groupId column of the craft_tags table with the new groupId for the tags you want to move.


Is there a way to define an attribute setter method on a model? I want to ensure that any attempt to set a date attribute on a model by way of populateModel() or myModel->foo = 'bar' (basically any method of setting a value) is intercepted so I can set a default if the value isn't valid.

Put another way, if you attempt to set a date prior to today (or a string that's not a date), I want to set the attribute to be today's date.

Currently I'm doing that in my populateModel() method but that doesn't catch the setAttribute('foo') approach or the myModel->foo approach.

For example in Laravel, we can create a setter method: setFooAttribute() so I was hoping for something similar.

In your model you can override setAttribute(), which covers calling setAttribute('foo', 'bar') directly as well as $model->foo = 'bar'.

public function setAttribute($name, $value)
{
    if ($name == 'foo')
    {
        // Not sure if your value will be a dateTime object, string, etc.
        // But check to see if it's < than today's current date.  If so,
        // set $value = new DateTime();
    }

    parent::setAttribute($name, $value)
}


Craft CMS with Foundation 6 workflow / installation I'm currently making a website with the Foundation 6 ZURB template, and want to connect to Craft CMS, but I'm pretty new at this stuff, and can't figure out wht the right installation and workflow would be.

So questions I'm dealing with:

Should I on my local machine install Craft, and change Foundation to build to that location?
Should I install them alongside each other (i.e. install Craft in the same folder as my Foundation)?
Should I make a fresh installation of Craft somewhere else, and install Foundation within the Craft structure somehow?

I found this on Github that looks interesting:
https://github.com/johanneslamers/craft-workflow

But I don't know how I would take it from there to get my existing Foundation code into the project. Could I just copy it over to this new installation?

Sorry if these are silly questions, but I want to get off on the right foot here. All help appreciated!

They aren't silly questions. There are a number of ways you might want to do this. Personally what I do on Craft projects when I've used Foundation is use the SASS only version which has directions located here: http://foundation.zurb.com/sites/docs/sass.html

You'll need to be familiar with NPM or Bower and Gulp to get the most out of that. If you're not familiar with them, do some reading there first. I stick exclusively to NPM since I have some other projects that I use Node for as well. This is up to your preference.

I do my local install of Craft in my new repository, set up environment variables and then install on dev/production servers as well. If you have a deploy process to install, I normally do that next so I am done configuring servers. Then I will install any npm packages and set up my gulp build process. I recommend using a lot of the same packages they have in that project like browser-sync. I am surprised I don't see autoprefixer in there which I feel is essential.

Should I on my local machine install Craft, and change Foundation to build to that location?

Yes but when you install Foundation via the method I mentioned above, it will build wherever you set it to build in your Gulpfile.

Should I install them alongside each other (i.e. install Craft in the same folder as my Foundation)?

I would not install the Foundation files in your Craft folder. This could make updates tricky. The core files will be in node_modules folder in your root anyway. When you locate your SASS files to build, I normally put those in public in their own folder at the same level as the compiled CSS. You don't have to deploy them to your server but it's helpful in local.

Should I make a fresh installation of Craft somewhere else, and install Foundation within the Craft structure somehow?

I think the above info probably answers this. Basically all Foundation related content I locate in the public folder wherever you want to locate your assets (sass, js, images, css).


Saving user profile photos to S3 Is there a setting to get Craft to save user photos to S3 like a regular asset source?

Craft 3 Update

This is currently possible in Craft 3.  Install the AWS S3 plugin from the Plugin Store. Make sure you're running Craft Pro.  Create a new Asset Volume using S3.  Go to Settings->Users->Settings in the Control Panel and set the "User Photo Location" setting to your S3 volume.

Craft 2

Currently no, although this is likely to change in the upcoming Craft 3.


Dealing with Upgrades and Git Workflow Craft updates come fast and frequent which introduces a problem when working with lots of people in a team.
Don't get me wrong, this is a good problem to have!

How are dev shops handling the update process when sites have multiple developers on them with multi feature branches running all at once?

The main issue is the strong dependency each feature branch has with the database. Once you implement a craft update, craft doesn't like jumping around on older versions as you switch feature branches.

What we're currently doing:

Disabling the ability for people to be able to update on the live production server.
Creating an "Upgrade" branch on git and doing the updates in that before merging them into the develop branch.

We still seem to be occasionally getting the odd issue of an old feature branch that is out of sync with the database/new install because of this we are still looking to improve this workflow.

Ideas we are tossing up:

Making a private repo of the /app directory a submodule so the sites repo is rather clean.
Disabling the ability to upgrade by default on all domains and treat updates as a "big thing" similar to how you would on an Expression Engine upgrade.

Would love to hear how others are tackling this "convenient" problem.

We at Familiar have decided to leave craft out of git because of this exact issue.  It's extra hassle every time an update comes out.

To better deal with it we've built a couple of grunt functions as part of our craft yeoman generator.  You can see the whole generator on npm: https://www.npmjs.org/package/generator-familiar-craft. Or just an idea of how the grunt tasks are setup: https://github.com/familiar-studio/generator-familiar-craft/blob/master/app/templates/Gruntfile.js

The tasks are pretty simple, the first one will download the latest copy of craft, unzip it and then move just the app folder into place (perfect if your local environment gets way behind)

We also have a database pull grunt task that grabs a copy of the live (or any staging) database and imports into your local database.

This way there's always a quick fix through one or both commands if things get out of sync on any of our developers local environments

So our normal update process is this

Update local to make sure everything's fine.
Update live
Celebrate!!
No committing needed.

Generally we treat craft just like any other project dependency manager like bower would and only add our own code to our repos


How can I create a visually weighted tag cloud? I kind of want a tag archive page where it doesn't just list all the tags and links to entries based on that tag, but where the sizes of the actual tag link vary based on frequency of use.

Any idea how?

Brandon commented on getting tag usage count (and how it can be expensive) in this Google+ post and again in this SE question where I was trying to think through a plugin.

So to completely steal from that, you could loop through your tags and get a count for each...

{% set tags = craft.tags.find() %}

{% for tag in tags %}
    {% set count = craft.entries.section('blog').relatedTo(tag).total() %}
    {{ tag.name }}
{% endfor %}

Then manipulate the listing with JavaScript or find the max count and loop again to apply inline CSS percentages or font-sizes that are scaled accordingly. As Brandon noted in that post, be sure to wrap everything in {% cache %} tags since this will be an intense template to render.

Update:

Since this answer, Phil Birnie released a plugin for this he's linked to below, and I came up with my own that we trashed in a Straight Up Craft Hangout thanks to Marion's stellar idea of using a Preparse field to tally counts, which I've added here as an alternative answer.


Is there a way to clear old database files from storage|backups folder automatically? We require a way to remove old db files from the storage|backups folder and I was wondering if there is a way to do this automatically or if someone has written a plugin that does it via a cron job?

******* Updated based on khalwat's comment ************

I don't think Craft does that automatically. Not sure about 3rd party plugins.

I wrote a custom controller function to run by Cron Job, and it's been working fine.

It does nothing but looping through the .sql files in the craft/storage/backups folder and delete the ones which are older than X days, based on the modified time of the file.

public function actionDeleteOldBackups() {
    try {
        $dir = 'craft/storage/backups';
        $backupFiles = scandir($dir);

        $x = craft()->config->get('xDaysToDeleteDbBackup') ?: 30; // Keep the backup files for 30 days by default. Change it to w/e you like.

        // Craft uses Greenwitch time to name the backup files
        $xDaysAgo = strtotime('-' . $x . ' days', time());
        // depending on how you want to compare the dates, the following line can be ignored.
        $xDaysAgo = strtotime(date('y-m-d', $xDaysAgo));

        // loop through files, find the file's last modified time and compare with $xDaysAgo
        if(!empty($backupFiles)) {
            foreach ($backupFiles as $fileName) {
                if(strpos($fileName, '.sql') !== false) {
                    $filepath = $dir . '/' . $fileName;
                    if(file_exists($filepath)) {
                        $created = filemtime($filepath);
                        if($created && $created < $xDaysAgo) {
                            // print_r($filepath . ' '); // for testing
                            unlink($filepath); //delete the file
                        }
                    }
                }
            }
        }

        \Yii::app()->end(); // no render
    } catch (\Exception $e) {
        die('Failed to delete dated backup files.');
    }
}

Put the function in one of the controller of your custom plugin, kindly reminder to allow anonymous access for this function. The URL for the Cron Job will be something like:

[host]/actions/pluginhandle/deleteOldBackups


Intercept all requests before a Controller Action is executed Is there a way to intercept a request before a controller action is run, so that you could preform additional authorisation checks?

Say I have an authorised user, but their access to actions is dependant on a 3rd party API. So I need a way to check, this 3rd party API or a stored session version, before each action is performed.

I can see the beforeAction() method, which is fine for new Controllers I have added, but I need site wide solution that will catch request that go through Craft and doesn't touch any plugins.

I can see the onBeginRequest Event, but aware this fires before Craft has had chance to setup. So I feel this might not be the best solution for me, as I would like to use services inside custom plugins. If there is no other way, I assume this is best place to look. If so what is the best way to add an Event listener for this?

You're correct about both beforeAction() and onBeginRequest().

However, you could put an init() method in your main plugin class file and this will execute on every request as long as the plugin is installed and enabled.

public function init()
{
    // Whatever code you were going to put in onBeginRequest can go here.
    parent::init();
}


Can I change the list of available locales? Is it possible, by any method, to change the list of available locales? The current list includes some strange entries, e.g. East Germany, and we would like to update this to be more current for our client.

You can download the locales you want from https://github.com/yiisoft/yii/tree/master/framework/i18n/data and place in your craft/app/framework/i18n/data folder and they will show up as options.

Since Yii ships with so many locales, we initially stripped a lot of them out to keep the Craft download size to something reasonable.

If there are some locales we stripped that you think should be included in Craft, hit us up at support@buildwithcraft.com and we'll get them in.


Live Preview not working - showing home page instead I've got a Structure entry, enabled, but Live Preview (or just viewing the page on the public site) shows the home page instead.

Might I have a setting incorrect?

Edit: It looks like previewing any entry shows me the home page.

My bad. I forgot to call the block in the _layout template!


Are there callbacks for elementSelect macro? I am writing a custom field type that makes use of Craft's asset selector, and saw that there is an elementSelector macro (in includes/_forms). I want to be able to do some things onSelect, but I cannot tell if that is possible with the elementSelector macro. I know the element select modals can be extended using Craft.createElementSelectorModal(). Is this the only way to access element select modal callbacks?

You can get the Element Select’s JS instance like so:

$(document).ready(function() {
  var elementSelect = $('#your-container-id').data('elementSelect');
});

(Replace your-container-id with whatever ID you passed into the id param when calling forms.elementSelect or forms.elementSelectField.)

Then you can attach a selection callback to that:

elementSelect.on('selectElements', function(elements) {
  // ...
});

There’s also a 'removeElements' callback function you can add.


Excluding an include template is there a simple way to exclude an 'include' for specific pages?

For instance I have an include {% include "_globals/_footer" %} but I don't want it to appear on my contact and 404 pages.
How would I exclude it?

Thank you!

There may be a better way, including adding exclusions as an array and checking if the segment exists in the array, but what about wrapping it in an if tag? This seems to work.

{% if craft.request.firstSegment != 'contact' and craft.request.firstSegment != '404'  %}
    {% include 'layouts/partials/my-template'%}
{% endif %}

Quick update: This is very rough but an example with exclusions array (doesnt account for other segments, just an example...

{% set exclusions = ['contact','404'] %}
{% if craft.request.firstSegment not in exclusions  %}
    {% include 'layouts/partials/my-template'%}
{% endif %}


413 “Request Entity Too Large” error with uploading a file In assets when uploading a medium size file I get this error:

  Failed to load resource: the server responded with a status of 413 (Request Entity Too Large)

What does it mean? And how to fix?

413 errors occur when the request body is larger than the server is configured to allow. Here’s how you can fix it, depending on your web server:

Apache: Set the LimitRequestBody directive in either your httpd.conf file or a local .htaccess file. (https://stackoverflow.com/a/3719358/1688568)

Nginx: Set the client_max_body_size directive in nginx.conf (http://www.cyberciti.biz/faq/linux-unix-bsd-nginx-413-request-entity-too-large/)

IIS: Set the uploadreadaheadsize config setting (https://web.archive.org/web/20160204040121/http://blogs.msdn.com:80/b/jiruss/archive/2007/04/13/http-413-request-entity-too-large-can-t-upload-large-files-using-iis6.aspx)

You also might want to try increasing PHP’s upload_max_filesize and post_max_size settings in php.ini or using the php_value directive in your .htaccess file if you’re using Apache (http://davidwalsh.name/php-values-htaccess).


Expected performance benefit of using a non-file CacheMethod (Redis, Memcache) I'm wondering what kind of performance increase, and in what situations, I might expect from using Redis or Memcache over the default file-based caching.

I know template caching always comes from the DB, so I'm not sure what else I can expect to be cached from Craft itself, and how that might impact site performance.

As with most performance related questions, the answer is "it depends". :)

Apps like Redis and Memcache store their key => value stores in memory as opposed to disk-based file caching.

Accessing data from memory is usually orders of magnitude faster than accessing data from disk.

All of these fall under "General purpose data caching" and Craft will use them internally for its own operations and plugins can certainly make use of them as well.

If you have a plugin that makes extensive use of data caching and/or you've got a heavily trafficked site, then you will likely see some tangible performance benefits.

If you're just doing a basic stock Craft install on a low trafficked site, then you likely won't see much of a difference at all.


Frontend Profile - Listing out Radio Buttons In the official documentation it explains how to let users customize user fields in the frontend, such as:

<label for="bio">Bio</label>
<textarea id="bio" name="fields[bio]">{{ currentUser.bio }}</textarea>

However I set some user profile fields that are Radio Buttons and can't find anywhere on how to output the field options in a form. I want to do something like:

<select id="radioButtons" name="fields[radioButtons]">
  {% for option in fields.profile.myRadioButtons %}
    <option value="option">{{ option | title }}</option>
  {% endfor %}
</select>

But obviously 'fields' isn't a twig variable. Is there a way to do something similar to the above?

You can access the field using currentUser.fieldHandle; and the 'labels' and 'values' of the field by looping through the options attribute. You can also set the selected state by checking each option for the option.selected property.

<select id="radioButtons" name="fields[myRadioButton]">
    {% for option in currentUser.myRadioButton.options %}
        <option value="{{ option.value }}" {% if option.selected %}checked{% endif %}>{{ option.label }}</option>
    {% endfor %}
</select>


How can I render a page template from a queue job/console controller? I'm trying to call craft\web\View::renderPageTemplate from within a console controller (also tried from a queue job), but running into all kinds of trouble:

E.g.

Exception 'Twig_Error_Runtime' with message 'An exception has been thrown during the rendering of a template ("Session does not exist in a console request.").'

I discovered the this was due to registerAssetFlashes: https://github.com/craftcms/cms/blob/279116ba4091edc67c92fcbbefc257bb4fe30335/src/web/View.php#L1418

No plugins that register twig functions/filters work

Currently I'm doing:

$view = Craft::$app->getView();
$view->setTemplateMode($view::TEMPLATE_MODE_SITE);
$view->renderPageTemplate($template, $variables);

The end goal is to render a template, cache it, and send the html to a web service.

How can I do this without everything breaking?

…Or is there another way to do this, or should this be a feature request?

Given that it's craft\web\View.php I think you're probably out of luck. Though it's only registerAssetFlashes() that seems to call getSession(), but I'm expecting more than just that may assume a frontend request. You could always ping a controller endpoint via Guzzle to return the Twig-rendered HTML to you though.


Updating all entries URIs after changing entry URL format After publishing some entries, I've changed the section setting "Entry URL Format" from news/{slug} to news/{id} but I had to re-save every entry to reflect the change.
Is there a better and fast way to update all entries URIs after changing the entry URL format?

The entries won't immediately get updated, as it could take a little while to go through all of them, but you should see a little progress bar in your CP header immediately after updating your section's settings, and if you click on it, it will give you more details -- saying that a "Resave Elements" background task is running. Once that has completed, your entries will have new URLs.

In my case, it was not working as indented with localised entries but thankfully that was fixed on build 2562.


Show the best sellers and the most visited products - Craft Commerce I´m working on a new online shop and want to show the best sellers and the most viewed products.

Is this possible to do with craft commerce? I guess so, since it´s a basic functionality, but I could not find how to do this in the docs.

thanks.
Sebastián.

This functionality does not currently exist natively in Commerce (June 2016).

You could probably use a plugin like entry count (https://www.putyourlightson.net/craft-entry-count) to achieve the most viewed (you might need to add commerce products support to that?).

For the best sellers, your best bet at the moment is probably to make a plugin that uses a query on the craft_commerce_lineitems table (along the lines of https://stackoverflow.com/questions/12235595/find-most-frequent-value-in-sql-column)...to return a twig variable of the n most popular product objects.


Upgrading Commerce 1 to Commerce 2 Folks:

I've got an e-commerce site that I'm upgrading. I've upgraded to Craft 3 and can reach the CP and the home page.

This site is tightly integrated with Commerce 1. When I visit the plug-in page, Commerce is listed but "missing". I've attempted to claim the license (using the license number listed on the plug-ins page) but the license number is not recognized.

Do I have any options other than purchasing a complete new license? Is there a way to use Commerce 1 with Craft 3?

You can not run Commerce 1 on Craft 3.

Commerce was completely re-written for Craft 3 compatibility.  Indeed the final release of Commerce 2 actually requires Craft 3.1.

That said, your license for Commerce 1 should work for Commerce 2 once you have that installed but note there is a lot more to upgrading sites to Craft 3/Commerce 2 than just installing the new versions - there are extensive changes needed to both - including template and fundamental changes to custom plugins if you have written any of those.

See:

https://docs.craftcms.com/v3/upgrade.html
https://docs.craftcms.com/commerce/v2/changes-in-commerce-2.html


Confusion over 'require login' behavior Quote from the {% requireLogin %} docs:

  This tag will ensure that the user is logged in. If they aren’t, they
  will be redirected to the Login page, and returned to the original
  page after successfully logging in.

Quote from the Login Form example in the docs:

  craft.session.returnUrl is set to the original URL that included the {% requireLogin %} tag that initiated the redirect to this login form. By default, users will be redirected based on your postLoginRedirect config setting value after logging in.

That seems to be contradictory - the first sentence saying the return path will be the page that contained the requireLogin tag and the second saying the return path is defined by a config setting.

I want to be able to have the redirect go to the page that calls the login (I have
 a few of them), but do not see a way of doing that. Using a return parameter in the login form does not work for obvious reasons.

Am I missing something here? Any wisdom greatly appreciated!

By default Craft checks the postLoginRedirect setting in your config. Depending on this value the user is going to be redirected to certain place. But if there is a value in the user session that's set when the requireLogin function is called Yii2 will use this value instead. So the workflow is the following

Check for a session value, if there is one, redirect the user
Check for postLoginRedirect value, if there is one, redirect the user
Redirect to homepage

  Using a return parameter in the login form does not work for obvious reasons.

Could you explain those obvious reasons? Because I always use the returnUrl from UsersController when I create a login via ajax.

You don't have to do anything actually. Just include the Twig token and Yii2 will handle it


How do I UNLOCK my account? My account is locked and I cant figure out how to unlock it. I tried resetting the password, but have yet to receive an email with a new one. Is there an alternative way to logging back on? I recently changed the password and because it is a shared dashboard, I think someone (who was unaware of the pw change) may have tried logging in too many times which is how the account locked.

If you don’t have access to another admin account, you could unlock the account directly in the database.

Change the lock value to 0 for the account in the craft_users table.


How can my plugin render a generic Matrix block in the Control Panel? Here's a sample of a matrix block:

I would like to have my own fields inside the block and retain the basic functionalities like Collapse, Disable, etc. Basically, just use the Matrix block UI without using the Matrix field.

Is this possible?

I was able to pull this off by referencing MatrixInput.js and /_components/fieldtypes/Matrix/input.html.


Calling Related Entries using the Element API I have two sections, each with a single entry type:

Sites
Locations

In the Locations entry type I have a Entries field called Site that you can use to relate a Location to a Site entry.

My questions is: how do I show which locations were related to a Site entry when using the Element API? I'd like to display it as an array when using a sites/.json endpoint.

This is what I've tried, but it breaks the endpoint:

'v1/sites/<entryId:\d+>.json' => function($entryId) {
  return [
    'elementType' => 'Entry',
    'criteria' => ['id' => $entryId],
    'first' => true,
    'transformer' => function(EntryModel $entry) {
      $locations = $entry->getChildren()->type('locations')->find();
      foreach ($locations as $location) {
        $locationsInfo[] = [
          'name' => $location->title
        ];
      }

      return [
        'id' => $entry->id,
        'name' => $entry->title,
        'tagline' => $entry->tagline,
        'about' => $entry->about->getParsedContent(),
        'locations' => $locationsInfo,
        'jsonUrl' => UrlHelper::getUrl("v1/sites/{$entry->id}.json")
      ];
    },
  ];
},

You’d do this with a brand new element query using the relatedTo param.

Craft 2:

// This is the PHP equivalent of typing `craft.entries()` in a template:
$criteria = craft()->elements->getCriteria(ElementType::Entry);

// Only fetch Location entries that are related to the Site entry:
$criteria->section = 'locations';
$criteria->relatedTo = ['targetElement' => $entry];

$locations = $criteria->find();

Craft 3:

// This is the PHP equivalent of typing `craft.entries()` in a template:
$query = \craft\elements\Entry::find();

// Only fetch Location entries that are related to the Site entry:
$query->section('locations');
$query->relatedTo(['targetElement' => $entry]);

$locations = $query->all();


How to set a dynamic title in plugin on entry save? I have a section of events and am trying to automatically set a readable title on the event entry in the CMS ( such as Jan 5 - 12, 2015 or Jan 5, 2013 - Jan 10, 2016 ). I realize I can do this via a Dynamic Title on the entry type, however my twig logic gets cut off, it seems it won't fit in the allowed character limit (220 ?). My twig code looks like:

  {% set start = object.startDate %}
  {% set end = object.endDate %}

  {{start|date('F j')}}
  {% if end %}
    {% if start|date('Y') == end|date('Y') %}
      {% if start|date('F') == end|date('F') %}
         – {{end|date('j, Y')}}
      {% else %}
        – {{end|date('F j, Y')}}
      {% endif %}
    {% else %}
      {{start|date(', Y')}} – {{end|date('F j, Y')}}
    {% endif %}
  {% else %}
    {{ start|date(', Y') }}
  {% endif %}

I have made numerous attempts at shortening this to fit in the character limit, below is my best attempt:

{% set s,e = object.startDate,object.endDate %}{{s|date('F j')}}{% if e %}{% if s|date('Y')==e|date('Y') %}{% if s|date('F')==e|date('F') %}–{{e|date('j, Y')}}{% else %} – {{e|date('F j, Y')}}{% endif %}{% else %}{{s|date(', Y')}} – {{e|date('F j, Y')}}{% endif %}{% endif %}

But it's still getting cut off. Perhaps there is an easy solution for this via some Twig magic?

I then moved to try to do this within a plugin. I put this in my main plugin class:

public function init()
  {
      craft()->on('entries.onSaveEntry', function(Event $event)
      {
          $entry = $event->params['entry'];
          if($entry->section['handle'] == 'dates')
          {
             $start = $entry->startDate;
             $end = $entry->endDate;
             $fullTitle = $start . " - " . $end;
             $entry->setContentFromPost(array(
               'title' => $fullTitle,
             ));
          }
      });
 }

I am fairly certain this code is running on save, however my title isn't updating. Any idea what I'm missing?

I have turned off dynamic titles for this section in the entry settings to ensure that wasn't interfering.

To get more code into the template field that generates the title I tried importing a macro, but this didn't work. So squeezing it into the 255 chars is probably our only chance here. So it would be in fact better to do it with plugin.

To get your plugin code working you should use entries.onBeforeSaveEntry instead of entries.onSaveEntry.

Because when this event is triggered, it's already too late to update $event->params['entry'] properties for your save.

Another thing to change is setContentFromPost(). Change the ContentModel directly
$entry->getContent()->title = $fullTitle;


Running Craft from two subdirectories We are trying to add Craft alongside another CMS. I currently have Craft setup with the Craft app directory above web root and then two web accessible sub-directories as follows:

blog
offer

Each subdirectory has a Craft index.php file in it, pointing to the one craft app directory above web root.

My issue now is trying to serve up a different set of pages based on which sub-directory the user accesses (ie. "www.domain.com/offer" or "www.domain.com/blog"). I thought I could add routes to do this but they don't seem to work as I'd hoped.

Are routes the right way to do this? I thought I could have defined a route of "blog/" to load a specific template but that does not work (I assume that first URL segment isn't available to the route based on having the index.php file in that directory?).

Is there another way to handle this that I haven't thought of?

Thanks,
Mike

There's a whole slew of PHP constants you can define in each public index.php file to separate out the templates, config settings, etc. for each of the sites.

It's a very similar method we use for https://craftcms.com, too (just based on subdomains instead of subfolders.


How long does a CSRF token lasts? I did at some point believe that the CSRF token my plugin requests was using expired in the middle of a request, but it turns out that they were never included in the first place.

Still curious, I wonder how long a CSRF token lasts?

Each session gets it's own CSRF token, so technically it will be valid as long as a session is valid.


Display Full Month Name Currently trying to get the date filter to display 'April' instead of concatenated version 'Apr'. My code below is:

{{ now|date("M, Y") }}

Try using this.

{{ now|date("F, Y") }}

You can find the format strings for the date filter: http://php.net/manual/en/function.date.php


Errors Saving Entries Suddenly getting errors when trying to save entries.
Have recently upgraded to latest version of Craft.

When I try up update a Single Entry I get the error:

Fatal error: Call to a member function getAttributes() on a non-object in /path-to-site/craft/app/controllers/EntriesController.php on line 484

When a try to save a Channel in IE11 it pops up - Do you want to open or save - 210-a-new-news-articlef93bf125.json(1.09KB) from domainname.com

What is causing this problem?

Sounds like something may be corrupt in your /app folder... I'd recommend performing a manual update to try to fix the problem.

If you are still experiencing this issue after performing the manual update, I'd recommend contacting Pixel & Tonic directly, to report this as a bug.

You can email them at support@buildwithcraft.com, or use the "Send a message to Craft Support" widget on your dashboard.


ERR_EMPTY_RESPONSE when accessing order data (MAMP) I've got a local installation of Craft 3.0.37 and Craft Commerce 2.0.0-beta.15 running on MAMP. When completing an order, an empty response is given by the browser. The same thing happens when trying to look at that error from the admin area.

When I look into the MYSQL logs, I see the following error for both situations:

2019-01-13T13:32:43.718637Z 300 [Note] Aborted connection 300 to db: 'DBNAME' user: 'root' host: 'localhost' (Got an error reading communication packets)

I've tried upping the limits of the MYSQL setup, but to no avail.

Try updating your MySQL config max_allowed_packet config setting to a higher value and verify the change has been applied to your running instance.

https://dba.stackexchange.com/questions/19135/mysql-error-reading-communication-packets


Trouble with submitting Contact Form plugin contact via AJAX I’m having trouble getting Contact Form to work when posting through AJAX.

Form:

{% macro errorList(errors) %}
    {% if errors %}

            {% for error in errors %}

{{ error }}

            {% endfor %}

    {% endif %}
{% endmacro %}

{% from _self import errorList %}

    <form method="post" action="" accept-charset="UTF-8">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="contactForm/sendMessage">
    <input type="hidden" name="redirect" value="contact/thanks">

Your Email

                <input id="fromEmail" type="email" name="fromEmail" value="{% if message is defined %}{{ message.fromEmail }}{% endif %}">
                {{ message is defined and message ? errorList(message.getErrors('fromEmail')) }}

Message

                <textarea rows="10" cols="40" id="message" name="message">{% if message is defined %}{{ message.message }}{% endif %}</textarea>
                {{ message is defined and message ? errorList(message.getErrors('message')) }}

                <input type="submit" value="Send">

THANKS

    </form>

jQuery:

$('#my-form').submit(function(ev) {
    // Prevent the form from actually submitting
    ev.preventDefault();

    // Get the post data
    var data = $(this).serialize();

    // Send it to the server
    $.post('/', data, function(response) {
        if (response.success) {
            $('#thanks').fadeIn();
        } else {
            // response.error will be an object containing any validation errors that occurred, indexed by field name
            // e.g. response.error.fromName => ['From Name is required']
            alert('An error occurred. Please try again.');
        }
    });
});

In this case the response is not a success so the alert is triggered.

Out of interest I console logged the response in the else block and it’s all the HTML on the page. And then I thought, why don’t I console log the data variable right after it’s declared and - same thing - it’s all the HTML on the page.

Anybody got any tips?

This is your html

<div id="my-form" class="form">

And This is your js event handler

$('#my-form').submit(function(ev) {

So $(this) is actually a <div> container element and $(this).serialize() is null so you'll send no data. You should add a id to your form

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

and send the form data instead of a div data.

var data = $("#myForm").serialize();

I reproduced it, and it worked - even though I would prefer sending an actual object instead of a serialized form, but that's only subjective


How do I get the next year? I can get the current year in this way:

{% set currentYear = now.year %}

How do I get the next year?

You can also get it with:

{% set nextYear = now.year + 1 %}


Craft 3: 500 Internal Server Error when trying to install on server For the last 3 days i've been trying to install Craft CMS 3 on my server.

I'm using 1&1 internet, have FTP uploaded all the files, changed the permissions for the folders and files to the right level and made sure everything is pointing in the right place.

It's worth noting i've installed Craft CMS 2 on this exact server for years with no issues at all. I also successfully installed Craft CMS 3 locally with no issues.

Going to mydomainname.com shows a craft error page with

HTTP 503 – Service Unavailable - craft\web\ServiceUnavailableHttpException

throw new ServiceUnavailableHttpException();

Going to /admin/install or index.php?p=admin doesn't work it just gives me an Apache Error screen with 500 Internal Server Error.

I've also tried using ssh and attempted to install composer but have been unsuccessful at that as my server doesn't seem to want to allow me to.

I need to get a website live asap and don't really know what I can do next! I'm not hugely experienced with servers etc.

Any advice much appreciated.

The 503 error on the home page usually indicates that Craft can't connect to the database. That's to be expected when performing a fresh installation.

The internal server error could be a typo or other misconfiguration in the /web/.htaccess file. You can troubleshoot this by renaming the .htaccess file so Apache doesn't use it, then in /config/general.php set

'omitScriptNameInUrls' => false,

index.php?p=admin should work then and you can sort out the .htaccess url rewrites later.


Possibility to use Craft's search function to search in PDF files I have a client who wants to search for specific PDF files when she makes use of Craft's search function. The way she wants the PDF's to be found is that the words inside of the PDF is somehow processed by Craft and when you search for certain words that are included in a PDF it will show results of PDF's that contain these search words.

I have Googled for a module that can do such a thing but so far I have no luck. Does anyone know if such a module/plugin exists for Craft or do I need to hire someone to create that for me?

Thank you for reading.

As far as I know, there is no ready-built solutions available for Craft that makes text in PDFs searchable.

You probably have to look into building this plugin yourself, or hire someone to do it.

Posting in the #jobs channel on Craft's Slack is a good place to start.


How do I use a Twig template to generate Email content from inside a plugin I'm making? I'm trying to do a nicely formatted email from a plugin I'm making. The standard way I've been doing simple emails is all entirely in the code, somewhat like this:

$notificationEmail = new EmailModel();
$notificationEmail -> toEmail  = $userEmail;
$notificationEmail -> subject  = "Subject here";
$notificationEmail -> body     = "Thanks $userName, you’re now registered on our website.";
$notificationEmail -> htmlBody = " ... MASSIVE COMPLICATED STUFF THATS FAR BETTER SUITED TO TWIG ... "
craft()->email->sendEmail($notificationEmail);

I've now got an email that is far better suited to being generated via a Twig template because I'm going to have to loop through relational fields and all sorts. I have no idea how and I don't seem to know what to Google to get what I'm after... Anyone got pointers to this sort of thing?

Thanks to Brad for providing the bulk of the answer. In more detail the line needing to be changed was this:

$notificationEmail -> htmlBody = craft()->templates->render('PLUGIN-FOLDER-NAME/TEMPLATE-NAME', ['theUser' => $user]);

I could then use {{ theUser }} (Which is a UserModel) in the TEMPLATE-NAME template to generate everything I needed.

So the full solution, to send an Email from a plugin, but using a Twig template to generate the HTML email content was:

$myEmail             = new EmailModel();
$myEmail -> toEmail  = $user->email;
$myEmail -> subject  = "Subject here";
$myEmail -> body     = "PLAIN TEXT CONTENT";
$myEmail -> htmlBody = craft()->templates->render('PLUGIN-FOLDER-NAME/TEMPLATE-NAME', ['theUser' => $user]);
craft()->email->sendEmail($myEmail);

Where $user was a variable containing a UserModel which I'd already got from previous code in the plugin I was writing.

https://craftcms.com/classreference/services/TemplatesService#render-detail for more detail (but for which I wish there were example code of how to use, and not just a dictionary).


Installing Craft 3 - Internal server error Using Ampps on Windows, I'm trying to install a fresh Craft 3.0 and I've followed the steps and everything seems to be working. Until the very last step, where Craft says "Oops something went wrong". Checking the console log I see the ajax call gets a 500 internal server error as response.

I can see that the database is getting filled up with tables etc so it seems Craft has a working connection to the database. I also tried to set devmode to True in general.php. When doing that I get the following when trying to access mysite.local/admin

An Error occurred while handling another error:
yii\web\ServerErrorHttpException: The info table is missing its row in D:\Git\festningen\vendor\craftcms\cms\src\base\ApplicationTrait.php:494

Is it a permission error? I can access files and folders in the web directory, and htaccess file looks normal:

<IfModule mod_rewrite.c>
    RewriteEngine On

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

I've also tried setting permissions on the folders, giving the users group full permissions. With no luck.

Any idea?

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

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


Special characters in `template->renderObjectTemplate` method Having a problem with the Formerly plugin where it is throwing an error if CSS is passed into the Submission body. Not sure if this is a Craft of a Formerly problem but looking into it further, the issue seems to occur when ! or ; are being passed into the templates->renderObjectTemplate() service - this results in an Unexpected character error being returned.

Any thoughts on how best to sanitise the input for this method so that form submission doesn't break?

The has been solved (kinda) - turns out CSS was being passed into the renderObjectTemplate method for an email template. This meant that Twig was (understandably) trying to process the { and } characters as objects which was causing the service to throw a wobble.

Have stripped out the CSS for now and will see if there is another way we can pass these characters into the service without breaking it.

Many thanks @robin on the CraftCMS Slack for help identifying and debugging the problem.


Using {% cache %} tags around {% template %} includes (or in Header) I was wondering if it makes sense to wrap these {% cache %} around {% include %} tags that call a separate file with params. Is it better to just include them in the actual file itself?

For example, I was using cache tags around includes that call main navigation HTML in the header, like so:

{% cache globally %}
  {% include '_partials/navigation/config.twig' with {
     menuLinks: menuNavLinks,
     direction: "right",
     type: "header"
   }%}
{% endcache %}

This was causing an allocated memory error that took me forever to debug. FYI I am running locally on XAMPP and my memory_limit is set to 128M; when I increased this, it caused even more issues, related to Database Exception "MySQL error 2006: mysql server has gone away."

Is this not advised and against proper {% cache %} practices?

General answer: It is not wrong to put include tags in cache tags.


Events documentation for Craft 3 I've been looking for an Event Reference doc for Craft 3 just like what we had for Craft 2, but couldn't find one. The only events doc I found for Craft 3 is the plugin updating guide: https://docs.craftcms.com/v3/extend/updating-plugins.html#events.

Did I miss anything? Appreciate if someone can post a link here.

Also, for Craft 2 events, we used to be able to do $event->params[$paramName] to get the params passed into the events, but I struggle to find a way to do similar things in Craft 3. Any suggestions?

Whilst Doug's answer is useful for knowing the ins and outs of a particular event once you've found it, actually finding which events are available in Craft 3 in the current docs is not straight-forward. After a bit of digging, you'll find that most events are part of Craft's services - so head to the Class Reference and choose the most relevant service from the craft/services menu. The events available to each service are listed at the end. For example: https://docs.craftcms.com/api/v3/craft-services-users.html#events


Password protected area with unique files We're considering using Craft for a new project. One of the features requested is to have a password protected area. Each user would have access to their own files only. So we'd need to be able to setup users and assign files to them. It also needs to be simple enough that the client could do this without our intervention.

I'm pretty familiar with how I would do this with EE but wondered if/how it could be done with Craft.

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

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

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

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

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

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

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

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

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

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

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

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


How can I loop through a collection in the index file? I am basically wondering where does this section('services') is set up and how. https://github.com/craftcms/demo/blob/3f224f1f2e260c3e18190b16420c2e661cbb35ee/templates/services/_entry.html#L22

I need to loop through the collection entries on the _index.html to display a small card for each one, but I don't know how to reach them from the index.

To set up a section (or check the one you are referring to), in your control panel, go to Settings then Sections.

To loop through entries on a template, for this service section for example, you do:

{% for entry in craft.entries.section('services').all() %}
    {{ entry.title }} <br>
{% endfor %}

Hope that helps :)


Solspace Calendar: custom fields not outputting I'm unable to get custom fields to output using Solspace Calendar on Craft3. I am not getting any errors indicating that the field does not exist, it's just not outputting. The field is a Redactor type.

{% set event = craft.calendar.event(segment2, {targetDate: occurrenceDate}) %}

{% if event %}

{{ event.title }}
 {# THIS OUTPUTS #}
        {{ event.eventDescription }} {# THIS CUSTOM FIELD DOES NOT OUTPUT AND THERE ARE NO ERRORS #}

{% endif %}

UPDATE: I tried using the field handles that are in the Solspace Calendar templates (location and description), but neither of those output:

{% if event['location'] is defined %}

        Location

            {{ event.location }}

{% endif %}

This is a known issue and will be resolved in Beta 4 coming out today (March 15, 2018). Sorry for the trouble.


Logistics of loose field naming and re-use with Relabel Relabel certainly seems quite useful in being able to apply a more generic use to fields. The more I use it the more I see a use case for just creating a generic field with the same name as it's fieldtype which can be re-labeled and re-used in specific instances. Is anyone doing something similar and are there any potential issues to that approach? It seems to make things much more modular and re-usable.

So, for instance you could create an instance of fields such as Plaintext called Plaintext, Richtext called Richtext, etc. Then just relabel them and provide specific instructions in an on-the-fly basis when required. That would help to cut down on the number of fields in use.

Relabel is a great plugin and the option to re-use fields without sacrificing semantics for the content editor can be very useful, especially if you (potentially) face creating a lot of similar fields (hundreds) in order to provide specific labels and instructions. I'm not aware of any technical or performance related issues with the plugin, but here's a couple of things worth considering before going all in:

Your content model will be less flexible. For instance, if you use the same Rich Text field everywhere, you're not going to be able to have different settings for different types of content (perhaps entry type X needs a different Redactor config than entry type Y, or you need to disable/enable HTML purification for a specific piece of content – there's no way to make that happen if you use the same field for everything). This is especially troublesome if you only figure out you need different settings for different types of content late in development (or even after initial development has concluded), i.e. after adding a ton of content to the site. Of course, this applies to Craft even if you're not using Relabel, but personally I always lean towards creating two fields if there's even a slight chance I'm going to need different settings for different things.
Your templates will be less semantic. Even if you add the labels "Hero text", "Body" and "Description" to a Rich Text field with the handle richText across your content in the CP, you'll still have to call {{ entry.richText }} everywhere in your templates. Losing the semantics and clarity of entry.heroText, entry.body and entry.description could make your code more confusing and harder to debug and/or read in the long run.


Image Transform path issue I have a multi-lingual site with a folder structure set up like this:

/craft
/assets
  -/images
/nl
  -index.php
/fr
  -index.php
index.php

I have an asset source set up like this:

File system path: assets/images/
File URL: http://krycer.be/assets/images/

This allows me to upload images without any problems and they are uploaded in the correct folder on the server.

I use image transforms in my templates by using the {{ asset.getUrl('imageTransformHandle') }} but this gives me errors. The images are not generated (there is no redirect to the generated image, the URL is linking to the cpResources/transform/ID).

When I try this code in devMode 'generateTransformsBeforePageLoad' => true it gives me an error that it cannot find the file (allthough it is definitely on the server).

I tracked this issue back to the fact that I have sub folders for my languages (nl/fr) and probably the image transform module searches a path from the local index.php file.
So when I adjust the asset source to ../assets/images/ the transforms are generated and I can see the images.
But then I have the problem that I can no longer upload any images because the path is not correct (because the asset source is probably looking in relation to the top index.php file, being the one above the nl/fr folders).

How do I fix this and is this a bug or is there an easy idea behind it I do not grasp?

The file system path has to be an absolute path from the root of your filesystem, like /Users/myuser/webserver/myproject/public/assets/images.

For portability between different environments, it's a good idea to make an environment variable that holds the path to your project, which you can then use in the assets file system path. This is described very nicely in the "Environment-Specific Variables" section of the "Multi-Environment Config" part of the docs.


Migration to new server, left with default theme? I have migrated a website that uses Craft CMS over to a new server. The instructions that I followed were outlines in this post: Migration of Craft CMS from one host to another

The domain name in question is : glosenterprise.co.uk - this is how its meant to look. Here is a screenshot of how it is looking on the server.

I am completely new to Craft CMS but to me it looks as though its not pulling in the theme that was created for the live site.

Is there anything obvious that I missing or a direction that people can point me in?

As written in the other comment. There were files from the fresh installation of Craft that I needed to delete. Once removed the template shown as intended.


Event when a sections' entry type changes layout? Is there a way or an event available to detect changes on the fieldlayout of an entrytype? We've wrote a piece of middleware that needs to be informed of such changes.

Thanks in advance,

Patrick

Not right now, and technically Craft actually deletes the old Field Layout and creates a new one each time you save an Entry Type, since it would be more trouble than it’s worth to keep the old one and compare it to the new POST data for changes.

So, we could add a new onSaveEntryType event to SectionsService, which would end up getting called whenever the Field Layout changes. I’ll add that to the 2.3 list.