Trying to set a dynamic twig variable using craft.request and a craft global I'd like to understand how to combine these two elements into a twig set vars.

--

Context: I'm building a dynamic template that will list entries from which ever section the URL segment loads. For example /news will be news articles.

Each template will have a page title variable that I'm sending up to the _layout master. The page title's are input using craft.global's I have them setup like this {{ news.pageTitle }}.

In my dynamic template I'm trying to load everything from the URL slug. For example if it loaded the /notices URL the template would render the global: {{ notices.pageTitle }}.

--

Craft global: {{ news.pageTitle }}

URL Segment (/news): {% set getSegment = craft.request.getSegment(1) %}

This works: {% set pageTitle = news.pageTitle %}

But this doesn't: {% set pageTitle = getSegment.pageTitle %}

Are you trying to look up the global variable {{ news.pageTitle }} by having the news part be dynamically set from the first segment?

This answer here might help explain. Then try this...

{% set pageTitle = _context[craft.request.getSegment(1)].pageTitle|default("News") %}

I don't think that's the best way to set the displayed page title for your sections, but I believe that's what you're trying to do.

A slightly nicer way would be to also create a page for each section/channel root and have its URL be the same as the base path you use for the entries in those sections. Then you could dynamically look up the page attached to any entry by using this (sorry it's complicated)...

{% set page = craft.enties.url(entry.section.urlFormat|split("{")[0]) %}

That should find the page with the URL that matches the URL of the section entries (up until the first dynamic part). Then you can use the page title, banner, or any other fields you've put on the page.


amforms no error handling I have this form (am forms plugin):

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

          {% for error in errors %}

{{ error }}

          {% endfor %}

  {% endif %}
{% endmacro %}

{% from _self import errorList %}

{% set form = craft.amForms.getForm('contactForm') %}

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

  {{ getCsrfInput() }}
  <input type="hidden" name="action" value="amForms/submissions/saveSubmission">
  <input type="hidden" name="handle" value="{{ form.handle }}">

   {{ 'Nachricht' | t }}*
   <textarea id="frm_message" name="fields[message]" value="{% if formHandle.message is defined %}{{ formHandle.message }}{% endif %}"></textarea>
    {% if form is defined %}
        {{ errorList(form.getErrors('message')) }}
    {% endif %}

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

</form>

This is not displaying any errors if the field is empty. What do I miss? I made the field required in the CP but the macro is not showing when hitting "submit" with the field empty.

Ahh this is a bit misleading because the docs don't really spell it out. "formHandle" according to the docs really feels like it might be the variable you set your form to, but it's literally the form handle you got when you titled your form in the CMS.

So if your form starts with:

{% set apple = craft.amForms.getForm('fireTruck') %}

your error code needs to be this:

{% if fireTruck is defined %}
    {{ errorList(fireTruck.getErrors('someField')) }}
{% endif %}

and not this:

{% if apple is defined %}
    {{ errorList(apple.getErrors('someField')) }}
{% endif %}


Craft 3 RegEx problem I am trying to change all rgb colours in a bit of text/content. I have the RegEx working here in php using preg_replace:

preg_replace("/#[a-zA-Z0-9]{6}|rgb\((?:\s*\d+\s*,){2}\s*[\d]+\)|rgba\((\s*\d+\s*,){3}[\d\.]+\)|hsl\(\s*\d+\s*(\s*\,\s*\d+\%){2}\)|hsla\(\s*\d+(\s*,\s*\d+\s*\%){2}\s*\,\s*[\d\.]+\)/", "*****", $input_lines);

https://www.phpliveregex.com/p/oc2

But cannot seem to get it working in craft template code am trying is like this:

{% set svg_image = '
#ffffff
#ffffffasdf
asdf#ffffff
rgba(170,221,255,0.59)
rgba(170,221,255,0.59)asdf
rgb(0, 0, 0)
rgb(33, 44,66)
rgb(0,0,0)asdf
rgba(170,221,255,0.59dsaf)
' %}

{% set svg_image_output = svg_image|replace({ '/#[a-zA-Z0-9]{6}|rgb\\((?:\\s*\\d+\\s*,){2}\\s*[\\d]+\\)|rgba\\((\\s*\\d+\\s*,){3}[\\d\\.]+\\)|hsl\\(\\s*\\d+\\s*(\\s*\\,\\s*\\d+\\%){2}\\)|hsla\\(\\s*\\d+(\\s*,\\s*\\d+\\s*\\%){2}\\s*\\,\\s*[\\d\\.]+\\)/': '****' }) %}
{{ svg_image_output | raw }}

I have:
 - added double-escaped '\' as the docs suggest in v2
 - started with / and ended with /

Seems in the docs that if this is done it works like preg_replace.

Any ideas?

You were close!

Just don't use the Twig hash/array syntax when using the |replace filter if you want Craft to process it as regex.  This should do what you're looking for:

{% set svg_image_output = svg_image|replace('/#[a-zA-Z0-9]{6}|rgb\\((?:\\s*\\d+\\s*,){2}\\s*[\\d]+\\)|rgba\\((\\s*\\d+\\s*,){3}[\\d\\.]+\\)|hsl\\(\\s*\\d+\\s*(\\s*\\,\\s*\\d+\\%){2}\\)|hsla\\(\\s*\\d+(\\s*,\\s*\\d+\\s*\\%){2}\\s*\\,\\s*[\\d\\.]+\\)/', '****') %}


How to create an Asset Source programmatically via a plugin? I've taken a look at app/services/InstallService.php for some inspiration, and I'm not great at navigating/understanding the documentation. I really don't know where to begin with this.

Could I get a little push in the right direction on how to create an Asset Source programmatically via a plugin please?

I'm hoping there's a way I can generate an asset source onBeforeInstall. I'll probably need a method to remove it too should  the plugin be uninstalled.

Thanks.

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

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

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

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

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

$source->setFieldLayout($fieldLayout);

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

You can look at the AssetSources controller actionSaveSource for reference.

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


How do you gain PCI compliance without certifying your server for Craft, with or without Commerce? This is going to be informational, as we had a good conversation over this area on Craft Slack. And good fun trying to get around the idiotic StackExchange 'subjective' monitor to publish it here -- couldn't imagine what this wanted.

Why would you want to avoid PCI compliance on your own server? Because it's a bank-level task to get and maintain it.

See the conversation linked in the answer below, thank you.

The takeaway is to use api packages provided by payment providers such as Stripe and Authorize.net. The Craft Charge plugin can very much simplify and smooth doing so with Stripe.

Here's a link to a Git Gist of the conversation, as Slack erases content within a week:

https://goo.gl/bYIFLV

As well, though I don't guarantee it will stay up, is an experiment with Storify to show the same thing. I'm not sure which version reads better -- maybe Storify on a mobile phone, one reason for trying it.

https://goo.gl/5hEcLS


How can I access the raw profile photo for any given user? I am using the profile photo on users' posts (author image) and I would like to provide a link to download a larger image. I am currently able to get the "full" size of the cropped image like this:

<img src="{{ entry.author.getPhotoUrl('original') }}" alt="{{ entry.title }}">

Is there a way to get to the image that looks like is stored here:

/craft/storage/userphotos/*

As you've discovered, you can get the full cropped version of the image with author.getPhotoUrl('original'), but Craft doesn't keep a copy of the original un-cropped version of the image around.

And Lindsey is more than 60% correct... user photos are 1st class Asset citizens in Craft 3, making this less awkward.


Install Craft in a subfolder of an ee site? I have an ee site which I can't move over to Craft yet (need a commenting plugin) but I need to extend the site quite a bit. I'm thinking of either installing Craft in a subdomain or a subfolder.

In a Friday chat Brandon advised to go with a subdomain, as having Craft in a subfolder of an ee site that I would/might run into session problems.

Is installing Craft into a subfolder of an ee site a complete no no, or are the potential session problems avoidable? Anything else to lookout for?

Thanks for any help.

In additional to the potential session headaches, you'd also have to worry about getting the .htaccess rewrite rules to play together for each installation considering they inherit from any parent folders.


Group entries by section How do I group entries by section? I have search results:

{% set entries = allowedSearchableEntries.search(query).order('score').limit(100) %}

But I want to have

SECTION NAME
entry 1
entry 4
entry 6

SECTION NAME
entry 3
entry 12

etc.

You can use the Twig group filter.

{% set entries = allowedSearchableEntries.search(query).order('score').limit(100) %}

{% set entriesBySection = entries|group('section') %}

{% for section, entriesInSection in entriesBySection %}

{{ section }}

        {% for entry in entriesInSection %}

{{ entry.title }}

        {% endfor %}

{% endfor %}


Back to paginated page While I know the back button does this perfectly well, I was wondering if there was a good way to "return to" a paginated page using a previous request or something? Wanting to do this server-side rather than relying on JS. Thanks.

The easiest way would be to check craft.request.urlReferrer and see if they just came from the entry index page. If so, provide a link to send them back.

{% set referrer = craft.request.urlReferrer %}
{% set indexBaseUrl = url('articles') %}

{% if referrer and referrer|slice(0, indexBaseUrl|length) == indexBaseUrl %}
    Go back
{% endif %}

Another, more explicit way to do it would be to actually pass the current page in the query string of the entry URLs, from the entry index page.

{% for entry in entries %}
    {% set url = url(entry.uri, { page: craft.request.pageNum }) %}
    {{ entry.title }}
{% endfor %}

Then you could check for that “page” query string param in the single entry template:

{% set indexPage = craft.request.getQuery('page') %}
{% if indexPage %}
    {% set indexUrl = url('articles/' ~ craft.config.pageTrigger ~ indexPage) %}
    Go back
{% endif %}


Getting this SQL Error: GROUP BY incompatible with sql_mode=only_full_group_by I am getting the following error:

  Internal Server Error CDbCommand failed to execute the SQL statement:
  SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #18
  of SELECT list is not in GROUP BY clause and contains nonaggregated
  column 'creighton_mma_craft.structureelements.root' which is not
  functionally dependent on columns in GROUP BY clause; this is
  incompatible with sql_mode=only_full_group_by

I have mysql 5.7.9 installed. Logging into the Control Panel is working fine, but the front end displays this message.

During the installation, the screen was stuck at the very end with "Ooops…" message.

I am new to terminal commands and mysql configurations so the more specific the better.

Thanks.

MySQL 5.7.5+ changed the way GROUP BY behaved in order to be SQL99 compliant (where in previous versions it was not).

There is a good overview of the changes here.

Unfortunately, this affects some core queries that Craft uses when fetching elements.

The good news is that this has been fixed already in Craft 3 since we refactored the way that elements query grabs data and it no longer uses a GROUP BY.

The bad news is that it's going to be pretty impractical to backport that fix into Craft 2.

The workaround for Craft 2, if you're running MySQL 5.7.5+ is to edit your my.cnf file and remove the ONLY_FULL_GROUP_BY option from sql_mode. That will change GROUP BY behavior back to its pre-MySQL 5.7.5 behavior.

Update:

If, for whatever reason (primarily you're on shared hosting), you aren't able to change the sql_mode of your box at the environment level, as of the next Craft release (post 2.6.2945), there is a new initSQLs database config settings you can set in your craft/config/db.php.  It will accept an array of SQL statements to be executed immediately after the database connection has been established.  If you're running into this MySQL 5.7 error, you can do:

'initSQLs' => array("SET SESSION sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';")

Just keep in mind this method will add at least one extra SQL query to every request.


What media type are SVGs treated as in assets? When SVGs are uploaded to assets what media type does CraftCMS associate them with? Image, Document, HTML or XML?

Image. Use the kind parameter to filter them out.


How to enforce capitalisation on users First Name and Last Name We have developed a Craft 3 site that has user registration. Once a user account has been confirmed and activated, they are shown in a Contacts directory, which other users can search through.

As the user is responsible for adding their own details, a few users have submitted their names in lowercase:

jamie wade instead of Jamie Wade.

Whilst there is nothing wrong with this, it doesn't look great. Is there anyway we can enforce capitalisation in Craft on the users First Name and Last Name fields?

I am aware of Twig's title filter, and this is a good fallback if there isn't anything else.

You could easily add client side (JS) validation before the user registration form is submitted. How to do that depends on your JS architecture, I'd use something like vee-validate with a regex validation.

However it would probably be more user friendly to just automatically do the title casing in a custom module, adding something like the following inside the module's init() function:

Event::on(\craft\services\Elements::class, \craft\services\Elements::EVENT_BEFORE_SAVE_ELEMENT, function(Event $event) {
    if ($event->element instanceof \craft\elements\User) {
        $event->element->firstName = \craft\helpers\StringHelper::titleize($event->element->firstName);
        $event->element->lastName = \craft\helpers\StringHelper::titleize($event->element->lastName);
    }
});

Just beware if you have international users. Who knows what this will do to their names. See Falsehoods programmers believe about names


A problem with {% elseif %} statement Here is my situation. This is not a whole code, only the part, where I'm having a problem. At the back end, model coverbackup is populated with files as well as model cover. If I depopulate cover (remove image from entry), I want to load model coverbackup. I was checking over and over, If I got to my file in matrix field correctly, but It seems I have.

Than I've tried to check if elseif statement loads anything on cover=false, I got empty output.

{# Get the slides stored in variable "slides" #}
{% set slides = craft.entries.section('handle').type(['article', 'blog', 'news']).order('RAND()').limit(3) %}

    {% if slides %}

        {% for slide in slides %}

            {% set cover = slide.coverImage %}
            {% set coverbackup = slide.entryContent %}

                    {% if cover %}
                        {% for cover in cover %}

                        {% endfor %}

                    {% elseif coverbackup %}
                        {% for block in coverbackup %}
                            {% if block.type == "image" %}
                                {% for image in block.images %}

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

     {% endfor %}

{% endif %}

The proper conditional statement in this case would be to test for the length property of your Asset field, i.e. cover:

{% if cover | length %}

The reason this works, is that calling slide.coverImage will – as long as the attribute "coverImage" exists for the "slide" model – never return a falsey value, even if there are no files. It will in fact always return an instance of the ElementCriteriaModel class, i.e. an object representing your Asset field.

What the conditional {% if cover | length %} does is to read the length property of the ElementCriteriaModel object. The length property will represent the number of images in the Asset field – if it contains 0 images, the conditional will evaluate to "false" – as the number 0 within a conditional is interpreted as a falsey value. If you prefer, you can also write the statement like this:

{% if cover | length > 0 %}


How to fix admin assets url-s on nginx? After moving a Craft website from Apache server to Nginx, the admin css\js assets url-s stopped resolving.
For example, on /admin/login page Craft CMS tries connecting to the /admin/resources/lib/jquery.min.js - even though that directory structure doesn't exist, it still connects fine on Apache server, but results in a 404 page on nginx.

How are these routes generated? What need to be added to vhosts file in order for it to work?

Note that Craft is used to generate only the part of the website - e.g. www.example.com/craftpages is my Craft homepage.

It just sounds like your nginx conf file isn't setup properly.  See here for some working examples.


Adding new locale - hangs at Step 3 'ResaveAllElements' I've looked at every option I can think of so hoping that someone can assist. We're on a dedicated server with full root access.

We've got a relatively small site that now needs a Spanish locale adding. When I go to add it, everything seems to be smooth running until 'ResaveAllElements - step 3' and 'ResaveElements - step 99 (sometimes around 94 ish too).

First thing I checked was the error log and found:

Allowed memory size of 268435456 bytes exhausted (tried to allocate 79 bytes)

So, I then changed this to 1024M - no joy. Changed it to -1 and still get exactly the same issue. These settings are reflected in the phpinfo too so they seem to be in place.

I then phoned our server company and ran it by them who suggested placing .user.ini files in there to be sure and so we've done that and now we're at a loss.

I found another post on here with a similar issue where the suggestion was to examine the craft.log - did that and found:

WHERE (lft = 1) AND (status = :status). Bound with :status='running') 2016/08/12 09:36:53 [trace] [system.CModule] Loading "components" application component in /*/craft/app/etc/web/WebApp.php (593) in /*/craft/app/models/TaskModel.php (81) in /*/craft/app/models/TaskModel.php (39)

Is there anything else we can try to get the locale that we've missed?

Any help would much appreciated.

Thanks!

You probably need to up Craft's internal memory limit, as well – the following should go into the array in your general.php configuration file:

'phpMaxMemoryLimit' => '1024M',


Why is Craft returning a 504 during a system update? There have been a few updates to the system and some of the plugins I am using. I have installed everything locally and a plugin needed to run new migrations as a result of the update.

Everything works great locally, I went to /admin to "Finish up" the updates.

Now I have moved the files out to my staging server. I always manually update (even though Craft will do this for me). Once all of the files have deployed, I once again visit /admin to run the migrations.

However, the database is quite large (> 100MB) and I am getting a 504 Gateway timeout error.

What can I do to fix this?

I've had this issue before.

It's usually to do with one of two things for me - either the PHP script timeout value or the FPM proxy timeout value.

Another method of fixing this is to change the update settings in the general Craft configuration:

'backupDbOnUpdate' => false,

Keep in mind though that you will need to back up the database yourself.


Using Sprig's live search but show all entries first I want to display all results in the games section to start with, then once you search, it shows the filtered results. Sprig's starting point I think assumes that you're showing nothing, like a normal search box.
With the code below, it shows all results to start with - but once there's a search query, it shows the filtered results, then also ALL of the results underneath those. What do I need to change to show all results first and REPLACE them with the filtered results after searching?
It's something to do with the s-target stuff I think. The original loop gets 'moved' into #results when you search, but as I don't understand how Sprig works so I don't really know why it's doing it
{% set queryParams = {} %}
{% set relatedParams = ['and'] %}

{# This is where the query logic is -combining category filters and text search etc #}

{% if sprig.include %}
    <select sprig s-target="#results" name="verdict" id="verdict">
        {# loop through options #}
    </select>
    <select sprig s-target="#results" name="rating" id="rating">
        {# loop through options #}
    </select>
    <select sprig s-target="#results" name="platform" id="platform">
        {# loop through options #}
    </select>
    <input sprig s-trigger="keyup changed" s-target="#results" type="search" name="title" id="title" />

{% endif %}

{% if queryParams %}
    {% set entries = craft.entries(queryParams).orderBy('score').all() %}
    {% for entry in entries %}
        {{ entry.title }}
    {% endfor %}
{% else %}
    {% set entries = craft.entries.section('games').orderBy('title').all() %}
    {% for entry in entries %}
        {{ entry.title }}
    {% endfor %}
{% endif %}

Looking at the example from the Sprig Cookbook, it looks like the results container should live outside the sprig.isInclude:
{% if sprig.isInclude %}
    <select sprig s-target="#results" name="verdict" id="verdict">
        {# loop through options #}
    </select>
    <select sprig s-target="#results" name="rating" id="rating">
        {# loop through options #}
    </select>
    <select sprig s-target="#results" name="platform" id="platform">
        {# loop through options #}
    </select>
    <input sprig s-trigger="keyup changed" s-target="#results" type="search" name="title" id="title" />
{% endif %}

<div id="results">
{% if queryParams %}
    {% set entries = craft.entries(queryParams).orderBy('score').all() %}
    {% for entry in entries %}
        {{ entry.title }}
    {% endfor %}
{% else %}
    {% set entries = craft.entries.section('games').orderBy('title').all() %}
    {% for entry in entries %}
        {{ entry.title }}
    {% endfor %}
{% endif %}
</div>


Workaround for deprecated regex pattern modifier in PHP 5.5.0 and up (10.10 Yosemite) I'm relying on the Low Regex plugin to convert section handles from camelCase to lower-dash-case to use them in URLs, like so:

{section.handle|regex('/(^|[a-z])([A-Z])/e', 'strtolower(strlen("\\1") ? "\\1-\\2" : "\\2")',(section.handle))}

…and further, to convert the segment of the URL that contains the dash-separated section name to camel case, so I can work with it in my templates, like so:

{% set sectionHandle = craft.request.getFirstSegment() %}
{% set sectionHandleCc = sectionHandle | regex('/-([a-z])/e', 'strtoupper(strlen("\\1") ? "\\1\\2" : "\\2")',(sectionHandle)) %}
{% set section = craft.sections.getSectionByHandle(sectionHandleCc) %}

Now, OS X 10.10 Yosemite ships with PHP version 5.5.14 pre-installed and as of 5.5.0 the e-modifier for regex patterns is deprecated, so on my local machine I get this error and the site breaks:

I got in touch with the plugin author and he suggested removing the e-modifier, which seemed to work within the templates, but when I removed the modifier in the sections entry URL format the CP wasn't able to re-save my entries and I couldn't save new entries either.

The question that remains is: Is there a workaround using a different regex pattern or – and that would be my preferred scenario – is there an approach I didn't think of that allows me to omit the plugin dependency completely? I guess one option would be to keep the section handles all lowercase, but I'd like to have them dash-separated in the URLs.

Okay, so, thanks to carlcs' answer I managed to solve the camel-case to lower-dash-case conversion. The other direction was a bit trickier, but again, after digging in a bit deeper I was able to figure it out myself:

First off, I'm not using the plugin any longer! Yay! The secret was to create a custom Twig filter that would convert dash-separated strings like so:

{{ 'my-first-car'|dash2camel }}
{# outputs 'myFirstCar' #}

With the help of this guide and some code from this answer I created my own custom Twig filter within Craft. Nothing fancy and hacked together quickly, but I've put it on GitHub if someone runs into the same issues.


Returning ElementCriteriaModel of entries via plugin I'm outputting an element criteria model in a Craft 2 plugin of some entries in a channel.  I noticed that when I fetch the entries the standard template way

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

I am then able to do something like the following to refine the number of entries with the lightswitch turned on:

{% set refinedEntries = entries.customLightswitchField(1)|length %}

However, when I fetch my entries in my plugin, output them into the template, then try refining it as above:

// plugin
$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'channelHandle';
$entries = $criteria->find();
return $entries;

// template
{% set entries = craft.myPlugin.fetch() %}
{% set refinedEntries = entries.customLightswitchField(1)|length %}

...I then get an Array to string conversion PHP notice.  I'm also not able to use things like .first() like I normally would.

Is this expected behavior?  Am I missing something when returning an element criteria model through a plugin?

Of course this is the expected behavior because you don't return an ElementCriteriaModel from your plugin.

You do return $criteria->find(); so you'll return an array of entries but not an ElementCriteriaModel if you want to return the object instead of the entries you have to do return $criteria.

As soon as you use the find() method Craft builds a query based on your ElementCriteriaModel, executes it and returns you an array of elements or null.


Output all translation strings to javascript object How can I output all translation strings to a javascript object?

Of course I could do it one by one like this:

<script>
translations.string = {{ "string" | t }};

...
</script>

But I want to just loop through all translation strings. Is there some kind of twig object containing all these strings?

Not that I'm aware of. You would have to create a plugin that scrapes all of your template files for translatable strings, that then also makes those strings available to twig templates.


Structure Navigation with 3 possible Link Types using Nav tag I'd like to build a Structure that can be used to output the main site navigation; each "entry" in the Structure would have three custom fields (types): Category, Entries, URL
This question is close to what I want, except it's not using Nav; I want children, so I think I need Nav? Plus I couldn't get that code to work anyway.
Based on other questions and the docs, I have this:
{% set pages = craft.entries.section('navDropDownMenu').all() %}

    {% nav page in pages %}

            {% if page.entriesFieldLink %}
                {{ page.title }}
            {% elseif page.urlFieldLink %}
                {{ page.title }}
            {% else %}
                {{ page.title }}
         {% endif %}
            {% ifchildren %}

                    {% children %}

            {% endifchildren %}

    {% endnav %}

The only thing that works here is the Category link, except it should be a child but it isn't. I'm new to Craft so I'm probably doing something basic wrong, but any help is appreciated.

I am doing something similar in using a Structure for the main navigation.  Below is what I have.  Hope it helps!
{% set menu = craft.entries.section('navMain').all() %}

{% nav link in menu %}

    {% if link.menuEntry|length %}
        {% if craft.app.request.absoluteUrl ==  link.menuEntry[0].url %}
        {{ link.title }}
        {% else %}
            {{ link.title }}
         {% endif %}
    {% else %}
        {% if craft.app.request.absoluteUrl ==  link.menuCustomURL %}
            {{ link.title }}
        {% else %}
            {{ link.title }}
        {% endif %}
    {% endif %}
    {% ifchildren %}

            {% children %}

    {% endifchildren %}

{% endnav %}


How to query entries and take into account the timezone offset? - ChartHelper I'm trying to query a range of entries and my results are not returning all the entries in the range I am trying to target. My situation relates to displaying data on a chart using the Craft ChartHelper class, but I'm not sure if this issue is specific to that situation or more general.

I believe Craft saves records to the database based on the UTC timezone. So if I'm in Los Angeles (UTC-7) and save an Entry on 2016-08-31 18:00:00 in Los Angeles, the dateCreated value in the database will be 7 hours later in the UTC/GMT timezone: 2016-09-01 01:00:00.

Now, I want to query all entries that happened in the month of August. The following, largely taken from the Craft Commerce chart codebase, gets me roughly what I need – entries that range over the month of August:

$startDate = DateTime::createFromString('2016-08-01', craft()->timezone);
$endDate   = DateTime::createFromString('2016-08-31', craft()->timezone);
$endDate->modify('+1 day');

$criteria         = $this->getElementCriteria();
$criteria->limit  = null;
$criteria->search = null;

$query = craft()->elements->buildElementsQuery($criteria)
  ->select('COUNT(elements.id) as value');

The above code gets handed off to the ChartHelper::getRunChartDataFromQuery() method which performs the query with this code:

$results = $query
  ->addSelect("DATE_FORMAT({$dateColumn}, '{$sqlDateFormat}') as date")
  ->andWhere(
    array('and', $dateColumn.' >= :startDate', $dateColumn.' < :endDate'),
    array(':startDate' => $startDate->mySqlDateTime(), ':endDate' => $endDate->mySqlDateTime()))
  ->group($sqlGroup)
  ->order($dateColumn.' asc')
  ->queryAll();

While I get back a month's worth of entries, the query does not return entries that were saved after 5pm on August 31st in Los Angeles. I believe this is because the dateCreated value in the database is actually on the following day, September 1st.

I would like to adjust this query to return entries from within the month of the timezone of the website – in this case Los Angeles.

Where do I need to adjust how the date values are being set in order to get back the right data?

I'm not sure what kind of server you are running, but you should be able to set the server timezone in your control panel. You may need to then restart your database in order for you database's settings to be updated.


How do i setup ajax paging for entries Im looking for a good way to setup paging for new items with a simple "load more" button at the bottom.

I know i'd use something like

{% if craft.request.isAjax %}

on the listing template to not include the main _layout file for the ajax requests and then using the paginate tags to control which entries to return.

Curious is anyone has a more streamlined approach

Hey So here is what i came up with, curious if anyone has a more streamlined approach.

https://gist.github.com/keithmancuso/17619fc405a621b4a11e

{% if craft.request.isAjax %}
    {% set layout = "_ajaxLayout" %}
{% else %}
    {% set layout = "_layout" %}
{% endif %}

{% extends layout %}

{% set limit = 10 %}
{% set params = { section: 'news', limit: limit} %}

{% block content %}

{% if not craft.request.isAjax %}

News

{% endif %}

{% paginate craft.entries(params) as entries %}
{% for entry in entries %}

{{ entry.title }}

    {{ entry.body }}

{% endfor %}
{% endpaginate %}

{% if not craft.request.isAjax %}

load more news

{% set pagingJs %}

$(function () {

    var page = 2;

    $('#loadMore').click (function (e) {
        e.preventDefault();

        $('#loading').show();

        $.get( "/news/p"+page, function( data ) {

          $( "#news-entries" ).append( data );
          $('.loading').hide();
          page++;

        });

    });
});

{% endset %}

{% includeJs pagingJs %}

{% endif %}

{% endblock %}


How to import user addresses? I have an existing database full of users with their addresses. I'd like to import this into Craft (Commerce), and have their addresses saved as their billing address.

The user import part is fine, I can use boboldehampsinks plugin to get the users in, and I can add custom fields to temporarily hold the address information until I can add it as their billing address.

Can anyone suggest a good way to go about this? The documentation for Craft Commerce doesn't seem to be as complete as for Craft, and I can't see a way to set a users billing address.

Thanks.

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

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

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

<?php
namespace Craft;

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

$craft->plugins->loadPlugins();

$addressModel = new Commerce_AddressModel();

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

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

$craft->end();

The above code will insert one Address.

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

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

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

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

This will make the address available for selection on checkout.


Is it possible to populate a user field in the CP using custom logic upon registration? Whenever a user is registered in the control panel, we'd like to have a special field (something like a special member id) that is populated either by manual entry or, if the field is left empty, run custom logic to generate a new value for that field.

Is this possible using Craft's events or by extending the existing user registration form available in the CP, or would it be easier to create a separate plug-in to handle the user creation process?

The Preparse plugin may help you accomplish what you want. https://github.com/aelvan/Preparse-Field-Craft


How to make use of Element Types I am building a plugin in Craft, I want to use the Element Types, the documentation seems so hard to grasp. Can you give an example or a template code?

Element Types are powerful and there are probably too many possible implementations to give a very meaningful example without additional information.

Here are a couple resources beyond the docs that could help you get started:

Master the Elements - A comparison of all native Craft CMS Element Types and what makes them unique.
Introduction to Element Types in Craft CMS - In this Hangout Brandon Kelly walks through a lot of details about Element Types. There are also a couple of other related videos you can find in the resources section here: Getting Started with Plugin Development for Craft CMS
Events Sample Plugin - Example plugin that demonstrates how Craft plugins can take advantage of Craft’s Element Type APIs.

I'd recommend taking a close look at the ElementType Class and related Element Type Model Class for each of the native Elements in Craft:

Asset
Category
Entry
Global Set
Matrix Block
Tag
User

Each Element implements the API slightly differently and understanding those differences will help you make sense of what you may need to include in your Element, or where you can piggy back on existing behavior.

There are also several plugins that use Elements. Each implementation is fairly custom, so which examples will work best for you are hard to say. Off the top of my head, there are plenty of examples:

Craft Commerce:

Commerce_Product Element
Commerce_Order Element

Sprout Plugins:

SproutForms_Form Element (Sprout Forms)
SproutForms_Entry Element (Sprout Forms)
SproutEmail_NotificationEmail Element (Sprout Email)
SproutEmail_CampaignEmail Element (Sprout Email)
SproutEmail_SentEmail Element (Sprout Email)
SproutSeo_Redirect Element (Sprout SEO)

A few others (if anybody would like to share others in the comments, happy to add them to the list)

Neo_Block Element (Neo)
SuperTable_Block Element (Super Table)


Tag mysteriously not found Weird issue where a tag was not found using the tags search query.  That tag is in the CMS (in news entries) as well as the DB, and even shows up in other queries.  Query in question:

{%
    set tag = craft.tags({
        search: { query: slug }
    }).limit(1)
%}

All but this tag can't be found for some odd ghostly reason.

You don't need to use the search parameter in this case. I'd avoid using it where ever possible.

{% set tag = craft.tags.slug(slug).first() %}


How to search children with relatedTo param My templates that referenced entry.children or entry.getChildren() have started throwing deprecation notices:

  Calling getChildren() to fetch an element’s target relations has been deprecated. Use the relatedTo param instead.

What is the preferred way to search for an entry's children — either ALL of its children, or just its direct children — using the relatedTo() param?

It appears the preferred way is by using getDescendants() — In fact, the children property is actually an alias for getDescendants(1). (The parameter specifies a maximum distance (i.e. number of levels) of the child from the parent.)


alternative global variable to siteUrl or the primary website? I am currently developing a multilingual craft website. To include assets like styles and scripts, I have so far built the URL following the pattern "{{ siteUrl }}/assets/css/main.css".

However, as soon as I change from German to English in the frontend of the website, the siteUrl changes, too, so that the styles and scripts can't be found anymore.

Is there another global variable, like {root_url} in expressionengine, which returns only the URL of the primary website or the root URL, regardless of the chosen language or site?

thanks!

You can define whatever aliases/environment variables you like. In this case, I'd probably define an environment variable in my .env file like this:

BASE_WEB=http://example.com

And then in config/general.php I'd add an alias:

<?php
/**
 * General Configuration
 *
 * All of your system's general configuration settings go in here. You can see a
 * list of the available settings in vendor/craftcms/cms/src/config/GeneralConfig.php.
 *
 * @see craft\config\GeneralConfig
 */

return [
    // Craft config settings from .env variables
    'aliases' => [
        '@baseWeb' => getenv('BASE_WEB'),
    ],
];

And then to use this in a template, you'd just do:

{{ alias('@baseWeb/assets/css/main.css') }}

...and away you go. To learn more, check out the Flat Multi-Environment Config for Craft CMS 3 article.


Craft CMS Entries Disappearing I've setup a Craft 3 site for a client and we are seeing the strangest thing where pages are just disappearing. Best we can tell no-one has deleted the entry, but we get a 404 on the front-end and it is not showing up on the back-end, even under "Trashed". What is weird is that when I re-create the page I can't use the same slug so it seems like it is still in the database. I've tried querying the database and I can see rows in the elements_sites table with that uri, but I don't know enough about the data scheme to tell where the disconnect is or tables to look at to determine which is the "live" version. One other note that may be related is several pages disappeared that were all sub-pages to a parent page (but the parent page is still there on the site)
Here is a query I ran for one of the pages that is missing:

Any suggestions for how to figure out what is happening or a query to run to determine which pages are live and where the disconnect may be for those pages?

I finally got to the bottom of what happened. I deleted a user about a month ago and after 30 days (the soft delete period) Craft deleted all related pages that the user had originally created. Thankfully, I was able to restore those pages by re-creating records for each in the entries table with a different authorid.
I ran this script on a backup of the database to find the entries for that author.
select es.uri, c.title, et.*, e.* from entries e
inner join entrytypes et on e.typeid=et.id
inner join elements el on e.id = el.id
inner join elements_sites es on es.elementid = el.id
left outer join content c on c.elementid = el.id
where e.authorid=DELETED_USER_ID
and el.revisionid is null

And then created insert scripts for the entries table for each one I needed to restore. The elements and other data was still in the database so I just had to re-create the entries records.
insert into entries (id, sectionid, parentid, typeid, authorid, postDate, deletedWithEntryType, dateCreated, dateUpdated, uid)
VALUES(ORIGINAL_ENTRY_ID, ORIGINAL_SECTION_ID, ORIGINAL_PARENT_ID, ORIGINAL_TYPE_ID, NEW_AUTHOR_USER_ID, ORIGINAL_POST_DATE, 0, ORIGINAL_DATE_CREATED, ORIGINAL_DATE_UDPATE, ORIGINAL_UID)


Including CSS/JS assets from template folder I cannot seem to include my CSS and JS files from the craft/templates/ directory into my website.

I've looked at this answer - Serving CSS files from template folder - and it tells me I simply need to have a styles/styles.css folder and I use {% includeCssFile "/styles/styles.css" %} and it should work. But it doesn't. I have a similar problem with the javascript includes. {% includeJsFile "js/lodash.min.js" %} command works, but once I navigate to any other URL, it tries to include the file http://localhost/craft/news/2016/js/lodash.min.js.

My folder structure looks like this:

I'm trying to keep all my assets in this craft/templates/ folder because I created a git repo in the craft main folder.

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

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


Display text field from Matrix of an Entry Field in Matrix Question is similar to some others I've looked through but their solutions don't work as there are some differences.

Currently this doesn't output any of the fields I try to access within the internal matrix.

{% for entry in craft.entries.section('sectionHandle').find() %}
    {% for block in entry.matrixHandle.limit(1) %}
        {% for entry in block.entryFieldMatrixHandle.first() %}
            {% for block in entry.entrysMatrixHandle.limit(1) %}
                {{ block.fieldHandle }}
            {% endfor %}
        {% endfor %}
    {% endfor %}
{% endfor %}

There's a couple of problems with your current code – for one, you're (as Brad mentions in the comments above) doing some variable overwriting by reusing the entry and block names. Also, you're attempting to do a for loop on the result from a call to first(), which won't work (first() returns a single element, not an array).

In any case, I'd suggest getting rid of all the for loops (you're looping on a resultset with a single element in each of your inner loops), in an attempt to make the code a tad more clear.

Something like this should work:

{% for entry in craft.entries.section('sectionHandle') %}
    {% set outerBlock = entry.matrixHandle.first() %}
    {% set outerBlockEntry = outerBlock ? outerBlock.entryFieldMatrixHandle.first() %}
    {% set innerBlock = outerBlockEntry ? outerBlockEntry.entrysMatrixHandle.first() %}
    {{ innerBlock ? innerBlock.fieldHandle }}
{% endfor %}

That's a lot of {% set %} statements, though – you could also do this (although I'm honestly not sure which option is more readable):

{% for entry in craft.entries.section('sectionHandle') %}
    {% set block = entry.matrixHandle.first().entryFieldMatrixHandle.first().entrysMatrixHandle.first()|default %}
    {{ block ? block.fieldHandle }}
{% endfor %}

Finally, as an alternative approach altogether you could use the relatedTo param:

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

    {% set block = craft.entries.relatedTo({
        sourceElement: entry.matrixHandle.first(),
        field: 'entryFieldMatrixHandle'
    }).first().entrysMatrixHandle.first()|default %}

    {{ block ? block.fieldHandle }}

{% endfor %}

None of the above examples are tested, and now my head hurts – but hopefully it'll prove helpful :)


RelatedTo "and" and arrays I have something I can not get my head around.

This works as expected:

.relatedTo(['and',{targetElement:22},{targetElement:33}])

But when I am building an array to use as relation criteria like so:

{% set related = [{targetElement:22},{targetElement:33}] %}

.relatedTo(['and',related])

Nothing returns.

It’s pretty late here in Berlin and I might be missing something simple but can not see what exactly. Anyone?

I don’t know what it is – I swear: every time – but the next thing I tried, immediately after posting the question was this:

{% set related = ['and',] %}
{% for relation in relations %}
    {% set related = related|merge([{targetElement:relation}]) %}
{% endfor %}

{% paginate craft.entries
    .section('documents')
    .relatedTo(related)
    as entries %}

That works.


Use Imager plugin with Element API? I'm trying to use the Imager-Craft plugin to make specific image transformations, but cannot figure out how to access Imager within the element-api.php file.

Imager shows plenty of template examples, but I'm not sure how to translate template code like this into straight Element API php.

{% set image = craft.assets().one() %}
{% set transformedImage = craft.imager.transformImage(image, { width: 1000 }) %}
<img src="{{ transformedImage.url }}">```

Specifically, I'm trying to access that craft.imager.transformImage function.

Is this possible?

In yii2 every instance of a module is stored in a public static property of the main class.

If the plugin is called image you can grab it via

Imager::getInstance()

This instance contains all the required components. The imager plugin it has 3 components

$this->setComponents([
    'imager' => ImagerService::class,
    'placeholder' => PlaceholderService::class,
    'color' => ImagerColorService::class,
]);

You can access those via Imager::getInstance()->imager or placeholder or color in this case the instance of the plugin is also stored in a static $plugin variable. You can call

Imager::$plugin->imager

as well. You can see a working example here

use aelvan\imager\Imager as Plugin;
....
return Plugin::$plugin->imager->isAnimated($asset);

This is the function that is being called when you do craft.imager.transform -> the PHP equivalent what you want to do


Problems Displaying Label and Instructions in Forms I am trying to learn how to create plugins using craft and am having a small problem.

On the templates/settings.html page I have the following code:

{% import "_includes/forms" as forms %}

{{ forms.lightswitchField({
    label: "Lightswitch Label"|t,
    instructions: "Lightswith Instructions"|t,
    name: 'lightSwitchName',
    on: settings.lightSwitchName,
}) }}

{{ forms.radioGroup({
    label: "Radio Group Label"|t,
    instructions: "Radio Group Instructions"|t,
    name: 'radioGroupName',
    options:{ "option_1" : "option_1", "option_2" : "option_2"},
    value: settings.radioGroupName
}) }}

What is interesting is that on the settings page for this plugin (in the admin control panel) the label and instructions only show up for lightswitch field and not for the radio group.  Here is a screen shot:

Am I doing something wrong?  Is there a way to display a title and instructions for a radiogroup?  If so, can someone please tell me how?

Thanks,

Moshe

You should be using forms.radioGroupField instead of forms.radioGroup, just like you're using forms.lightswitchField.


EVENT_REGISTER_TABLE_ATTRIBUTES not working in Craft 3 I am developing a plugin to add custom column to entries table for which I am using EVENT_REGISTER_TABLE_ATTRIBUTES and EVENT_SET_TABLE_ATTRIBUTE_HTML and code example is:

Event::on(
    Element::class,
    Element::EVENT_REGISTER_TABLE_ATTRIBUTES,
    function(craft\events\RegisterElementTableAttributesEvent $e) {
        return array(
            'foo' => "Foo",
            'bar' => "Bar",
        );
});
Event::on(
    Entry::class,
    Element::EVENT_SET_TABLE_ATTRIBUTE_HTML,
    function(craft\events\SetElementTableAttributeHtmlEvent $e) {
        if ($e->attribute === 'foo') {
            return 'bar';
        }
});

Unfortunately, its not working. Could anyone please help what I am mistaking here.

You don't need to return anything in an event. As you can see how the Event is triggert

Event::trigger(static::class, self::EVENT_REGISTER_TABLE_ATTRIBUTES, $event);

It does not expect any return value. So you don't add something by returning an array. Instead you'll have to manipulate the properties of your event

When you take a look at your RegisterElementTableAttributesEvent it contains the following property

/**
 * @var array List of registered table attributes for the element type.
 */
public $tableAttributes = [];

In order to add attributes you have to do

Event::on(
    Element::class,
    Element::EVENT_REGISTER_TABLE_ATTRIBUTES,
    function(craft\events\RegisterElementTableAttributesEvent $e) {
        $e->tableAttributes['foo'] = [
            'label' => "Foo"
        ];
});

It's the same for your SetElementTableAttributeHtmlEvent. It has the properties

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

/**
 * @var array|null The table attribute associated with this event.
 */
public $attribute;

/**
 * @var string|null The HTML to represent a table attribute.
 */
public $html;

You can var_dump the $event to see the current properties to get to know which structure you have to include. Usually you would do

Event::on(
    Entry::class,
    Element::EVENT_SET_TABLE_ATTRIBUTE_HTML,
    function(craft\events\SetElementTableAttributeHtmlEvent $e) {
        if($e->attribute === 'foo'){
            $e->html = 'FOOOOO';
        }
    }
);


Shouldn't the asset "View source" privilege limit access to an asset source in the selection modal? I've created an asset source: 'restricted uploads' and a user: 'Jim', who is a member of the 'staff' User Group.

Neither 'Jim' or the 'staff' group have any privileges for the 'restricted uploads' source.

If Jim logs into the admin panel and goes to 'Assets' in the sidebar, he can't see the "restricted uploads" source (as expected).

However, if Jim opens a file selection modal which includes access to the "restricted upload" source he can see "restricted uploads" listed in the modal source sidebar, and can select files from that folder.

Shouldn't Jim's missing asset "View source" privilege prevent him from being able to see the files in the "restricted upload" folder?

There is an issue filed for this here https://github.com/craftcms/cms/issues/887 that you might want to consider thumbs-upping or commenting on.


Are there any file-based static cache options for Craft CMS? Is there an option for storing the pages generated by Craft CMS as flat, static HTML files?

The model used by static driver from ExpressionEngine's CE Cache add-on works pretty well:

Each page request hits a mod_rewrite rule, which checks to see if an HTML file for that page exists in the static cache directory.

If said file exists, it gets served to the browser.

If the file doesn't exist, the CMS generates the output, which is then saved as a cache file for the next user who hits that URL.

It only works in cases where the entire page can be saved, but, it's insanely fast and pretty easy to implement compared to other caching solutions.

... is there anything like that available for Craft CMS?

Someone has recently developed a standalone static HTML caching plugin for Craft CMS which does similar to what you're after:

HTML Cache plugin for Craft CMS

This Craft plugin will generate static HTML files for your website. No need for Reddis/Varnish setups anymore!

Improves the speed drastically: 300-1500MS to 2-50MS (depending on
server setup) if ubercache is enabled from the settings page
Busts the cache automatically when an entry has been updated
Cache duration time can be set; defaults to 3600 seconds (1 hour)
Active development and support through Craft's Slack

NOTE: This plugin is still in beta, so please test if this plugin works as expected on a development environment before pushing to a production site.


Will the v3 upgrade be free? I'm seeing a lot of goodies among the v3 infos, but not much about how licensing will work.

So if my client has a paid license will they get v3 for free or as a paid upgrade. If paid will it be a full price or a discounted?

All Craft CMS updates are free of charge - including major versions. In other words, Craft 3 will be a free upgrade.

Edit

As announced under DotAll 2017, following the release of Craft 3 in April 2018, P&T is changing the pricing model for Craft CMS. In order to stay updated, Craft 3 sites will have to renew their license yearly (for a reduced fee; $39/year for Client edition, $59/year for Pro) in order to continue to receive updates after the first year.

Note that Craft 3 will still be a free upgrade for Craft 2 licenses purchased before the release of Craft 3, as these licenses will be exempt from the yearly updating fee and will continue to receive free updates indefinitely.

Source: https://craftcms.com/news/dot-all-2017-announcements


Create Plugin, Elementtype suggestion Let's start with this I have Jobs, which would be added from the front end and backend as well, thouse jobs have to have Clients and Workers attached to them, which are basically users with differnt fields, the workers they have to have ability to login in the system, the clients maybe too in the future, that's why I would like to ask which will be the best way to accomplish this? I did some basic plugins in craft, but this one is more complicated and I woud like to ask for the best way of doing it. I was thinking if it's possible to use UserElementType to accomplish this.  I'm very new in craft so some plugin or some code snipped would be veryhelpful for me thanks in advanced!

You likely won't need to write a plugin at all – you can easily create different user groups (e.g. "Workers" and "Clients") from the Control Panel, and grant those groups different permissions. An example of a permission is "Access the CP". The user group permissions will be automatically applied to any new users added to the group.

To create a user group, visit Settings -> Users in the CP. The edit form for a user group will have a plethora of checkboxes for every possible permission. Note that when checked, many of these checkboxes will actually reveal even more checkboxes, for even more fine grained control over permissions.


HTTPs Site - Redirects Go to HTTP First & Then HTTPs So I've updated the site URL in my general.php as follows:

    'siteUrl' => "https://" . $_SERVER['HTTP_HOST'],

I also have our web server making sure everything goes to https://www.example.com. Our IT person set this up but as I understand it it's done through vhosts in Apache.

Here is our .htaccess file:

<IfModule mod_expires.c>
 ExpiresActive on
 # Perhaps better to whitelist expires rules? Perhaps.
 ExpiresDefault "access plus 1 month"
 # cache.appcache needs re-requests in FF 3.6 (thanks Remy ~Introducing HTML5)
 ExpiresByType text/cache-manifest "access plus 0 seconds"
 # Your document html
 ExpiresByType text/html "access plus 0 seconds"
 # Data
 ExpiresByType text/xml "access plus 0 seconds"
 ExpiresByType application/xml "access plus 0 seconds"
 ExpiresByType application/json "access plus 0 seconds"
 # Feed
 ExpiresByType application/rss+xml "access plus 1 hour"
 ExpiresByType application/atom+xml "access plus 1 hour"
 # Favicon (cannot be renamed)
 ExpiresByType image/x-icon "access plus 1 week"
 # Media: images, video, audio
 ExpiresByType image/gif "access plus 1 month"
 ExpiresByType image/png "access plus 1 month"
 ExpiresByType image/jpeg "access plus 1 month"
 ExpiresByType video/ogg "access plus 1 month"
 ExpiresByType audio/ogg "access plus 1 month"
 ExpiresByType video/mp4 "access plus 1 month"
 ExpiresByType video/webm "access plus 1 month"
 # Webfonts
 ExpiresByType application/x-font-ttf "access plus 1 month"
 ExpiresByType font/opentype "access plus 1 month"
 ExpiresByType application/x-font-woff "access plus 1 month"
 ExpiresByType image/svg+xml "access plus 1 month"
 ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
 ExpiresByType text/css "access plus 1 year"
 ExpiresByType application/javascript "access plus 1 year"
</IfModule>

<IfModule mod_deflate.c>
 AddOutputFilterByType DEFLATE text/html text/plain text/css application/json
 AddOutputFilterByType DEFLATE application/javascript
 AddOutputFilterByType DEFLATE text/xml application/xml text/x-component
 AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml
 Addtype font/opentype .otf
 Addtype font/truetype .ttf
 AddOutputFilterByType DEFLATE image/x-icon image/svg+xml application/vnd.msfontobject application/x-font-ttf font/opentype font/truetype
</IfModule>

<IfModule mod_rewrite.c>
     RewriteEngine On

    #301 redirect with trailing slash
        RewriteCond %{REQUEST_URI} /+[^\.]+$
        RewriteRule ^(.+[^/])$ %{REQUEST_URI}/ [R=301,L]

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

</IfModule>

However, in tracking how redirects are working, it looks like most redirects, including adding an extra / to the end of a URL via the .htaccess, those done in Craft templates themselves and those done through the redirect manager plugin 301 to http://www.example.com and then 301 again to https://www.example.com. Visits to http://www.example.com redirect straight to https://www.example.com and visits to https pages directly return a 200.

How can I configure Craft to out the first redirect to http and just go straight to https? Thanks!

Think we figured out the root cause of this - we have a load balancer in front of our origin server and, long story short, that load balancer was communicating with our origin server via HTTP, causing the extra http redirect.

Fixing that issue would be a long and arduous process so, through some infrastructure updates, we'll be moving away from using the load balancer entirely.


Connection between twig template and website content I am new to Craft and I am basically inheriting a site that I now need to maintain.  I am a developer, not really a web designer, and my current task is to change the layout on the homepage.  Something simple, I thought.

What I am trying to wrap my head around is the connection between the web content that is defined in Craft and the twig files I see in templates.

So in website content when I look at the Homepage, I see text boxes and other content containers that appear to be where an end user could maintain "changeable" stuff.  Going further, I can see in Settings the "Section" for homepage where there is name, handle, template, etc as well as option to "Edit Entry type" where it seems that you don't layout the page as much as define what parts of the page will be editable content.  Is that correct?

So "Define Your Field Layout" is a bit of a misnomer?  You aren't designing the layout as much as defining what content your "layout" will contain?  So that leaves me with:  Where do I actually lay out the page?  Where is stuff positioned "just so"?  I don't see a WYSIWYG tool for that.  So, can I assume that the "Entry Template" listed in the section is the twig for the actual layout of the content?  In this case, there is 'index' as a value there so I should look for an index.twig that will contain the html and css for the page?

I am just trying to piece together the components. The last piece, if my assumptions above are correct, is that the index.twig, when I find it, will have twig markup that points back to the fields in the "layout" I saw in the section definition?

There just seems to be many moving parts and my past experience with CMS's is if you fail to understand how stuff hangs together then you tend to do too much work to make it work, rather than following convention.  As a developer, my first instinct is to write code, which can be a bad approach with a CMS...

Just want to confirm if my understanding of the basic connections is correct..more questions after I start breaking stuff...

Thanks

Yes, I think what you're saying is completely correct.

Settings > Sections > Homepage > Edit entry type

The "layout" here is only meant for the back end. This is just how you assign fields you want entries in that section to use and what it will look like for admins to create and edit entries.

Settings > Sections > Homepage

Will show you what template is being called when there's a match for that URI.

In the file system, your template files will be located in either /craft/templates if you're using Craft 2, or just templates if your using Craft 3. It's probably worth noting that these directories are usually above the web root.

For example:

.
├── craft
├── templates
└── web <-- web root
    └── index.php

If you're afraid of breaking things on a live site, you could create a duplicate of the site and run it locally or on another server. That's a great way to sandbox changes and play with things to see what effect they have.

Another great way to learn how Craft works is to try out the "Happy Lager" demo site. It's a pretty simple Craft site and well organized. I've see live production sites that are incredibly complex or over-engineered. I can't imagine trying to learn Craft with one of those as my only example.


Including the category group in nested category URIs? I've asked already about nested categories here, but I've just upgraded to Craft 3 and things seem to have changed a little.

I have three top-level category groups:

- Home
- About
- Funding

Each of these has multiple categories, and some of these categories are nested up to three levels deep.

My problem: the nested category URIs don't include the category group (which I appreciate doesn't have its own slug). Instead I get stuff like this:

/cat-A/subcat-1/
/cat-B/subcat-2/subcat-6/

... when what I want is:

about/cat-A/subcat-1/
funding/cat-B/subcat-2/subcat-6/

If I manually add funding/ or about/ as part of those categories' URI formats (eg. funding/{parent.uri}/{slug}) then it appends funding/ at each level, eg: funding/funding/funding/cat-B/subcat-2/subcat-6.

I've managed to achieve what I want for entries, by setting their URI format like so:

{category.first().group.handle}/{category.last().uri}/{parent.uri}/{slug}

... which gives me stuff like:

funding/cat-B/subcat-2/subcat-6/entry-title-slug

I only really need this feature to work because I envision users browsing the categories and potentially clicking the URI/links and being taken to the wrong place.

In my earlier post I created a top-level category group called "Navigation" which contained all my categories – this achieved the correct URIs. This feels messy/hacky though and means my users have to see a redundant "Navigation" group when editing categories.

It's likely I'm misunderstanding some aspect of Craft here – can anyone help me achieve what I'm trying to do here?

You would just enter { parent? parent.slug : '' }/{ slug } in the "Category URI Format" Field in the Craft3 CP and it will recognize nested categories


Getting an asset Url from an entry loop into a meta tag I found it pretty straightforward to get something like dynamic page titles working by setting a variable at the template level and pulling that into my site's meta tags:
My _layout.twig:
<head>
{% if title is defined %}
<title>{{ title }}</title>
{% endif %}
</head>

My template.twig:
{% set title = entry.title %}

But what's the best practice for pulling something like an asset URL that needs queried from within {% block content %}? I'm running a for loop on my asset field to grab the Url from within the template, but this doesn't seem to work outside of {% block content %}, and if I run it from within {% block content %} the variable doesn't carry over to _layout.twig where I need it in the meta tag.
My _layout.twig looks like this:
{% if openGraphImage is defined %}
<meta property="og:image" content="{{openGraphImage}}" />
{% endif %}

But how can I define an image Url that's coming from within an entry query and have it pass back to the meta tag?

I didn't have a full understanding of how blocks work, but I've solved my problem. I think because I was trying to set the variable in my template outside of the block (and I was trying to bring it into my _layout.twig file without referencing the block I was calling) nothing was getting properly passed from one file to the other. The solution I'm now using looks like this:
_layout.twig:
<meta property="og:image" content="{% block ogImage %}{% endblock %}" />

template.twig:
{% block ogImage %}
    {% for image in entry.eventImage.all() %}
        {{ image.url() }}
    {% endfor %}
{% endblock %}


Ajax submissions using SproutForms I need to submit a form, using SproutForms, via AJAX, so i can get the response and then show some "gated" content on the page. The content (i.e. PDF link, etc) is tied to a particular entry page, so i'd like to stay on that page and not doing a normal POST to a generic success page. I can't find any info on the SproutForms plugin page on how to do this, just that it's supported (noted in the change log). Please help

I figured it out (edited with my FORM mark-up as well):

I'm actually rendering the FORM using the SproutForms method:

<div class="submit-via-ajax">
    {{ craft.sproutForms.displayForm(block.gatedContentForm.first().handle) }}
</div>

and then my JS looks for any form submissions from a ".submit-via-ajax" block

// process the form
$('.submit-via-ajax form').submit(function(event) {

    // get the form data
    var formData = $(this).serialize();

    // process the form
    $.ajax({
        type        : 'POST', // define the type of HTTP verb we want to use (POST for our form)
        url         : 'sproutForms/entries/saveEntry', // the url where we want to POST
        data        : formData, // our data object
        dataType    : 'json', // what type of data do we expect back from the server
        encode          : true
    })
        // using the done promise callback
        .done(function(data) {

            // here we will handle errors and validation messages
            if (data.success == true)
            {
                // show/hide content/elements
            }
            else
            {
                // show an error
            }
    });

    // stop the form from submitting the normal way and refreshing the page
    event.preventDefault();
});


"Custom" validation for plugin settings page I have a plugin that has a few settings. One of which is a start date and and end date. Everything is set up and working fine. I'd like to validate the start/end dates a a bit though.

I am able to use compare to check that the end isn't before the start, but I'd also like to check that the start (or end) isn't in the past as well.

Using this awesome page on validation I've seen how to set custom validation via rules. But, since I'm in a settings file, I'm not exactly sure how this translates over.

MyPlugin.php

defineSettings(){
    return array(
        'myStartDate' => array(
             AttributeType::DateTime,
             'required': true,
             'compare': '<= myEndDate'
         ),
         'myEndDate' => array(
             AttributeType::DateTime,
             'required': true,
             'compare': '>= myStartDate'
         ),
    )
}

What I think I'm trying to get is something like this:

....
'myStartDate' => array(
     AttributeType::DateTime,
     'required': true,
     'something': array(
          'rule': myValidation,
          'message': 'The start date can not be after the finish date.'
      )
 )
....

function myValidation() {
    // Do something here
}

Or, maybe I'm way off.

It sounds like you're on the right track. You could create a custom validator, as detailed here.

<?php namespace Craft;

use Carbon\Carbon;

class MyPlugin_ExampleModel extends BaseModel
{
    protected function defineAttributes()
    {
        return [
            'startDate' => [
                'type'     => AttributeType::DateTime,
                'required' => true,
                'compare'  => '<= endDate',
            ],
            'endDate' => [
                'type'     => AttributeType::DateTime,
                'required' => true,
                'compare'  => '>= startDate',
            ],
        ];
    }

    public function rules()
    {
        $rules = parent::rules();

        $rules[] = ['startDate', 'validateFutureDate'];
        $rules[] = ['endDate', 'validateFutureDate'];

        return $rules;
    }

    public function validateFutureDate($attribute)
    {
        $value = $this->$attribute;

        if ($value && Carbon::now()->gte($value)) {
            $message = Craft::t("Date must be in the future");
            $this->addError($attribute, $message);
        }
    }
}

You can also extract the validation into a separate class, which would make it easier to test (details are in the aforementioned article).

Caveats and disclaimers

This code is completely untested. In particular, I'm not sure whether the date comparison will work with the attribute value as-is. You'll probably also want to check what happens to the custom validation if the value contains an invalid date-time string.


Fetching Matrix rows with Javascript Is there a way to use Craft javascript API to fetch all Matrix rows of a specific field on the entry edit page?

If not, could that be added? Would be useful, for example in terms of fetching the handle/id and using that in the frontend to simulate Matrix inside Matrix.

The Craft.MatrixInput class that manages each Matrix field doesn’t actually get assigned to a variable, so there’s no way to reference it right now. We probably won’t change that, since there wouldn’t be much point to it in the first place. The class doesn’t provide any sort of object-oriented API for managing the blocks; there’s no need for it in the current implementation.

If you want to get a reference to all the blocks’ containers, you can just use a jQuery selector:

var $blocks = $('#fields-myMatrixField > .blocks > div');

$blocks.each(function() {
    var $block = $(this),
        id = $block.data('id');
    // ...
});


How do _you_ protect input against XSS? ("HtmlPurifier"?) I've been playing with Craft for days now and love it. I'm new to Yii but I think I got the hang of everything and how you develop a Craft Plugin. My question is regarding security on input post/get vars.

Reading Yii's documentation is seems the "HtmlPurifier" filter is suggested to protect against XSS - but everything seems to be applied on output?

My question is: Does Craft do anything to "clean" input data OR how do you protect your data against malicious input?

I want to clarify that the data submitted by the user has gone through the validation rules in the Record/Model. Is there anything else you need to keep in mind?

When dealing with XSS concerns, it's important to stay focused on the fact that this is a client-side issue... So in regards to Craft, Twig is the star of the show.

Fortunately, Twig takes measures by default to ensure that your output is safe. For example, any time you're outputting some HTML code via a Twig variable, you're required to add a raw filter to get the HTML to render properly. Otherwise, those special characters get encoded and simply rendered "as is" on the front-end. When you apply the raw filter to a Twig variable, you're essentially telling Twig that you trust whatever data may be coming out of that variable.

Here are a few other Twig filters which may help you out:

escape
striptags

Your question puts an emphasis on data input, which isn't typically where XSS issues are addressed. However, there are some things (as you noted) which can help you sort out incoming data.

Validating your data using Yii validation rules is a good start. And I believe the CHtmlPurifier can be useful to you as well. Skimming through the Yii documentation, I believe this helper method can be applied to input data:

$purifier = new \CHtmlPurifier();
$purifier->purify($html)

  http://www.yiiframework.com/doc/api/1.1/CHtmlPurifier

Simply apply that helper method to data as it's being stored in your Record, and that should make your data safe for future output.


Send e-mail only to users related to entry with Postmaster/Sprout I would like to set up Postmaster or Sprout Email to send an e-mail notification when a new entry is added. I only want the email sent to users who are linked to the entry via a custom field (type:user).

I've having trouble solving this without writing a plugin to extend either plugin. If I have to write a plugin to do this, any tips? Otherwise, how can I do this with either plugin?

To reiterate:

How can I have notifications sent only to users who are linked to the new entry via a custom field (type:user)?

If I'm correct in thinking that you want users who have been added to a relation field on an entry to receive an email, then the following will work.

You will have to write a plugin to listen for the onSaveEntry event. You can then loop through any users added to the custom field of the entry and send them an email.

The code would look something like the following:

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

    $entry = $event->params['entry'];
    // The users field returns user id's
    $userIds = $entry->getContent()->users;

    // Grab the user models using the id's from the entry field
    $criteria = craft()->elements->getCriteria( ElementType::User );
    $criteria->id = $userIds;
    $users = $criteria->find();

    // If we have users
    if ( $users ){
        // For each user
        foreach ( $users as $user ){
            // Builds and sents the email
            $email = new EmailModel();
            $email->toEmail = $user->email;
            $email->subject = "You've been added to an entry";
            // Use this for a plain text email body
            $email->body = '';
            // This uses a html body from a twig template, you can pass the entry to it to access the entries fields
            $email->htmlBody = craft()->templates->render( 'pluginname/_emails/email-template-name', array(
                'entry' => $entry
            ) );
            craft()->email->sendEmail( $email );
        }
    }
});


Get entries from client checked options I have a checkbox field to enable my client to choose what entry categories to have as an article feed on a page. How can I output the checked option categories when setting the entries in the for loop? Below is what I have done to return the checked option's value but what I want to do is use the checked options value to filter through entry categories.

What I'm looking to do is set the entries as below:

{% set entries = craft.entries.relatedTo(category, 'checkedOptionValue','checkedOptionValue','checkedOptionValue').limit(10).find() %}

<!-- This is returning the checked options value -->
{% for option in checkboxFieldHandle.options %}
    {% if option.selected %}
        {{ option }}
    {% endfor %}
{% endfor %}

Any help would be greatly appreciated

The most straightforward way would be to use a Categories field.

The value that a Categories field returns to the template is an ElementCriteriaModel, which fits perfectly as a value for the .relatedTo parameter.

So you could do something like:

{% set featuredEntries = craft.entries.relatedTo( entry.selectedCategories ) %}

The only circumstance where I can envision a Checkboxes field being better suited to this use-case is if you need to only provide a specific subset of the categories in a group.

(If you want to make all the categories from a group available for selection, using a Categories field is definitely best; otherwise you have to go back and update the options of your Checkboxes field every time a category is created, changed, or deleted.)

In that case, I recommend using the category IDs as the option values for your checkboxes, so that you can pass them to an ElementCriteriaModel like this:

{% set featuredEntries = craft.entries.relatedTo( entry.selectedCheckboxes | join ) %}


How do you output the value of a checkbox item? Seems like it should be simple but it's not working for me.

{% for option in entry.contributionType %}
     <li> {{ option.value }} </li>
{% endfor %}

This code outputs the option's label instead of  the value. I feel like I'm going crazy.

Ok, just figured it out. Apparently, when I changed the value of the fields in the settings I had to re-save all entries that used that field. And not just re-save them, but reset the value in the field as well, because it had lost it's checked value when I opened the entry up to edit it.

I see now the warning in the field settings I had previously overlooked, "Changing this may result in data loss."


Craft 3 Docs Group Filter Not Working I am attempting to replicate the example from https://docs.craftcms.com/v3/templating/filters.html#group

However, I am unable to access the {{ year }} in the first for loop inside the h2 element. It just shows up as an empty string. Anyone have an idea whats going on?

Here is my code:

{% set allEntries = craft.entries.section('weeklyDigests').all() %}
{% set allEntriesByYear = allEntries|group('postDate.year') %}

{% for year, entriesInYear in allEntriesByYear %}

{{ year }}

   {% for entry in entriesInYear %}

{{ entry.title }}

   {% endfor %}

{% endfor %}

You were close!  In Craft 3, postDate is a full PHP DateTime object, so it'd need to be something like:

{% set allEntriesByYear = allEntries|group('postDate|date("Y")') %}


Nest Entries from Different Sections I have 2 separate sections living in the same place on my site. Example:

About (Single-type Section)

Team (Structure-type Section)

So in the URL I need to nest Team underneath About, i.e. /about/team. Since they're not in the same section I can't do it the built-in way, so how would I accomplish this?

The Team section’s landing page could just be a template living at about/team/index.html. From there if you want to output info about the team members, just fetch it manually:

{% for teamMember in craft.entries.section('team') %}

{{ teamMember.title }}

    ...
{% endfor %}

If you want to give each Team entry its own page on the site, go into the Team section’s settings and check the “Entries in this section have their own URLs” checkbox. Set the URL Format to about/team/{slug}, and the Template to about/team/_entry. Then create an about/team/_entry.html template with whatever info you want. (The current Team entry will be available to the template as an entry variable.)

From the index, within that for-loop, you can link to the team member’s pages like this:

{{ teamMember.title }}


MySQL "Access denied for user" after moving to new server I've moved my Craft 3 installation to a new server.

When connecting to the original database, everything works fine.

However, when trying to connect to a new MySQL database (I've tried hosting this on both the new server and RDS) I'm getting the error: Access denied for user. I migrated to the new database by exporting via the Craft CP and then importing to the new database via MySQL Workbench.

I've tried connecting to both servers using a vanilla PHP connection (i.e. new mysqli(host, username, password) and it works perfectly fine -- I can even query the database and return results.

I only run into this error when the connection is opened by the original Craft index.php (the one with the $app->run() command). I've checked the output of the (new Dotenv\Dotenv(CRAFT_BASE_PATH))->load(); line and it does properly return the settings defined in .env, which are the same as the ones used in the vanilla connection I mentioned above.

The side-effect of this error in storage/logs/phperrors.log is Allowed memory size of <memory_limit> bytes exhausted ... in /var/www/craft/vendor/yiisoft/yii2/db/Connection.php.

Seems this is not a Craft issue at all, but an issue with MySQL connections over PDO. Not sure of the precise environmental conditions that cause this, but I was experiencing the issue on both an AWS EC2 Ubuntu server as well as a MySQL RDS instance.

I discovered the solution here: https://stackoverflow.com/questions/38809418/unable-to-connect-to-aws-rds-through-pdo

In short, the ! in my password was causing the problem. After replacing it with a ., the issue is resolved.

Thanks Amazon...


Looking for a good explanation on Craft login and if it is using persistent cookies or session cookies, etc...? I am coming from a .NET/C# authentication and session environment.  I have used {% requireLogin %} to create a secure area on the front-end of my website, but it seems that the login credential (or cookie) stays persistent after the browser is closed.  There does seem to be time factor as the next day a login is required, but the same day after a somewhat short period with the browser being closed I can relaunch the browser and I have full access to the secure areas and the system knows my user account, etc...

Looking for some direction to explain the Craft security and cookie lifespan in more detail.

You're probably looking for the userSessionDuration config setting where you can adjust the length of time an authenticated Craft session should have (or just have it session/browser based).

Other related session config settings you might be interested in:

https://craftcms.com/docs/config-settings#elevatedSessionDuration

https://craftcms.com/docs/config-settings#rememberedUserSessionDuration


How can I delete entries from an entries field from a front-end from? I have an entries field that lives on a user's profile. I am using ajax to add entries to this field.

Example: "Click to add to favorites". Everything works great.

Now I am trying to delete an entry from the entires field, and I'm not quite sure how to pass the right data back to my controller.

Here is what my js looks like:

var data = [];
$('.remove').click(function (event) {
    var clicked = $(this).data('id');

    $('input[name="fields[myEntriesField][]"]').each(function (key, val) {
        var value = $(val).val();

    if (clicked != value) {
        data.push(value);
    }});
});

    ...

onRemove(data, function (response) {
    // response
});

function onRemove(data, callback) {
    data[window.csrfTokenName] = window.csrfTokenValue;
    ...
    // ajax
}

What I am doing here is adding all of the entry id's to my data array EXCEPT the one that I clicked on. I was going to pass that array to my controller.

Let's say I have 3 entries in my entries field. This is what is returned:

["1131", "1363"]

It's every entry except the one I clicked on.

In my controller I was going to loop through the array (of entry ID's) and re-populate the entries field - save the user.

I'm getting stuck trying to add the CSRF token - since I am passing in an array I guess I can't seem to append the CSRF token.

The above is currently getting me this far:

  The CSRF token could not be verified

If I log out all of the data just after I append the CSRF token, I get this:

["1131", "1363", _token: "TOKEN_NAME|TOKEN_VALUE"]

I've read through this SO thread. Which works - but I don't want to actually delete the entry - in essence I just need to re-populate the field.

Thank you for any suggestions!

EDIT

I've ben able to pass the value(s) to my controller, but now just struggling how to actually re-populate the entries field.

This is what I'm passing into my controller:

data: Array(2)
    0:"1131"
    1:"1363"
_token:"TOKEN_NAME|TOKEN_VALUE"

In my controller, I can access the values like this:

error_log(print_r(craft()->request->getPost('myField'), true));

Array(
    [0] => 1131
    [1] => 1363
)

Now just to repopulate the entries field?

// fields[myEntriesField] is an entries field type.
$userModel->getContent()->setAttributes(array(
    'fields[myEntriesField]' => , ???
));

Here is what I came up with that seems to be working well. Please let me know where there is room for improvement so others (including myself) can benefit!

JS

var arr = [];
var data = {};
$('.remove').click(function (event) {
    var clicked = $(this).data('id');

    $('input[name="fields[myEntriesField][]"]').each(function (key, val) {
        var value = $(val).val();
        arr.push(value);
    });

    // Check if we are sending anything.
    if (arr.length == 0) {
        data.arr = null;
    } else {
        data.arr = arr;
    }

onRemove(data, function (response) {
    // response
});

function onRemove(data, callback) {
    data[window.csrfTokenName] = window.csrfTokenValue;
    ...
    // ajax
}

Controller

 $userModel->getContent()->setAttributes([
     ...
     'myEntriesField' => craft()->request->getPost('fieldHandle'),
 ]);

Now if I click the "Delete" button, each entry is removed from the user's profile. If I delete the last entry, I pass null to the controller. This tells Craft that there are no entires to save in the entries field.

Hope this helps someone else!


Allowing duplicate slugs in category paths Again, I've had a look online but couldn't figure out what I had to do.

Say I've got a category structure like the below:

Category 1

Saturday
Sunday

Category 2

Saturday
Sunday

How can I allow duplicate category slugs so that they can be like:

/category-1/saturday/*
/category-2/saturday/*

Instead of:

/category-1/saturday/*
/category-2/saturday-1/*

What I have found online talks about Entries and Routes and then setting it up do serve from specific template but I'm not really sure where to start with that as still trying to learn how to work with Craft.

For example, this answer mentions how it should be possible if the Entry URI Format has been set up correctly for Sections but I haven't set up sections for creating categories so I'm not sure how my case relates (if it's of any use, I embed a screenshot of what I am referring to and category structure below):

Is there not a simple way to just achieve duplicate slugs for categories as per my above example?

If I try changing the slug to say 'saturday', it just re-appends the -1 to the end again.

Jamie's answer is correct.

If you set your Settings → Categories → Category URI Format to {parent.uri}/{slug} you will then be able have multiple time the same slug.

Craft will take the parent into consideration when saving the category therefore allowing you to have (in your case) byc/saturday and wbr/saturday


How to darken an image using the Imager plugin I'd like to 'darken' an image using the Imager plugin. How would I go about doing this?

I'll explain the exact effect I'm after in Photoshop terms: I have an image on one layer, then I create a new layer above it and fill it with black. I then change the opacity of the black layer to 40%. This is the end result that I'm trying to achieve with the Imager plugin (ImageMagick is available too).

I realise I could add a div with a black background over the images and change the opacity of this div, but I think it would be nicer if I could do this with the Imager plugin instead if this is possible.

This is the closest I've managed to get so far, but it doesn't quite match what I'm seeing in Photoshop:

{% set image = block.image.first() %}
{% set transformedImage = craft.imager.transformImage(image, {
  width: 1500,
  height: 700,
  effects: {
    vignette: ['none', 'black', 3],
    modulate: [100, 80, 100],
    gamma: 0.7 }
}) %}

Thanks in advance for any help with this.

Seems like you might be better using colorBlend?

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


Redirects or Routing for Landing Page URL's? I am trying to set up a channel that uses different content for a series of Google Adwords landing pages.

I set up the channel template as /landing-pages/_entry

I'd like to remove the /landing-pages/ piece of the title

Ideally, I'd like short simple url, which is effectively the slug title, which would be something like /chef-jobs for this client.

What is the best way to achieve this with Craft? Redirects or Routing.

The routing method doesn't call the entry and just shows a blank template, how can I feed the route address across if I use this method?

Any help, much appreciated :)

You can either set the URL Format of the landing pages channel to {slug} (the same as your normal pages)

Or you could try putting the landing pages in the normal pages structure, but give them a new entry type so you can use different fields.


Failed to add a custom field in settings I'm trying to add a global set, with a Matrix and two required fields for a product. This always works.

Now that I am in version 2.6.2791 it fails to add the fields with error:

Warning
: Declaration of Craft\UserSessionService::login($username, $password, $rememberMe = false) should be compatible with CWebUser::login($identity, $duration = 0) in
/Applications/MAMP/htdocs/craft-app/2.6.2791/services/UserSessionService.php
on line
17

Warning
: Declaration of Craft\UserSessionService::afterLogin() should be compatible with CWebUser::afterLogin($fromCookie) in
/Applications/MAMP/htdocs/craft-app/2.6.2791/services/UserSessionService.php
on line
17

Warning
: Cannot modify header information - headers already sent by (output started at /Applications/MAMP/htdocs/craft-app/2.6.2791/services/UserSessionService.php:17) in
/Applications/MAMP/htdocs/craft-app/2.6.2791/framework/web/CHttpRequest.php
on line
1519

Warning
: Cannot modify header information - headers already sent by (output started at /Applications/MAMP/htdocs/craft-app/2.6.2791/services/UserSessionService.php:17) in
/Applications/MAMP/htdocs/craft-app/2.6.2791/framework/web/CHttpRequest.php
on line
1507

The CSRF token could not be validated.

Any ideas or fixes would be great!

You're getting that error message because your PHP environment is displaying PHP Strict mode error messages.

By default, Craft will explicitly disable those if devMode is enabled (error_reporting(E_ALL & ~E_STRICT);) and disable all messages if devMode is disabled (error_reporting(0);).

So my guess is you've either got a plugin that's messing with error_reporting and re-enabling strict messages or you've doing it from your public index.php or craft/config files.

Note that in the upcoming Craft 3, we've made it so that you can run Craft with PHP strict error messaging enabled.


Include related entry slug in URl I've got a channel named "locations" that has an entry fieldtype which allows me to select the corresponding store/brand (limited to 1).

How can I define the slug of the related entry in Entry URL Format of a locations channel?

The final result should look like this: {related-entry-slug}-{slug} of the location entry itself.

Thank you.

Assuming your store/brand field handle in your new channel is relatedEntryField, set your URL format when you're defining the channel section to:

{relatedEntryField.first().slug}-{slug}

That'll pull the slug from the first related entry, add the slug from your current entry, and populate your URL.

As an aside, relational fields are always "arrays" even if there's only one so you need .first().


"Excerpt" option in Redactor? I love using the excerpt option in Wygwam (CKEditor). I've looked high and low but as of yet, have been unable to find a way to have an exceprt show short of having a whole second field. I have seen a custom Twig filter running around that would allow to show first paragraph (which I could modify to show whatever) but I like the ease of doing it straight in the WYSIWYG. Anyone have any options? (looking for a solution for a news roll page)

(First P Twig filter)
https://gist.github.com/james2doyle/6629712

You could use the Redactor's pagebreak plugin. Check out the docs.

If activated in your Redactor config, you will have the option to insert page breaks to your content, via a new “Insert Page Break” toolbar button.

Now you can get the first "page" in your template:

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

{{ entry.title }}

        {{ entry.richTextFieldHandle.getPage(1) }}

        {% if entry.richTextFieldHandle.getTotalPages() > 1 %}
            Continue reading…
        {% endif %}

{% endfor %}


Sub-Entries: Adding new Entries on Entries field I'm trying to write my first CraftCMS-Plugin.
It should behave like the "Entries" field, so I inherit from it.

The difference is:

I don't want to allow the user to select existing entries.
They should just add "news" to the "team".

The user visits his team
There are no news assigned to the team yet
He clicks the "add" button
A new News-Entry is generated (see Screenshot, i like the Quick-Add widget)
The News-Entry is automatically "linked" to the Team

I just don't know how to start.
The field is already in place and it inherits from "Entries".

But how can I "move" the "Quick-Add" Button from the "Select-Modal" (see screen) to my Field-Type. It seems to just trigger a POST-Request.

Is there an event i can trigger manually or how does this work, how can I hook in?

The thing you are talking about is a Craft.BaseElementEditor

You can see a working example within all ElementIndex js files

Craft.createElementEditor(this.elementType, {
    hudTrigger: this.$newCategoryBtnGroup,
    elementType: 'craft\\elements\\Category',
    siteId: this.siteId,
    attributes: {
        groupId: groupId
    },
    onBeginLoading: $.proxy(function() {
        this.$newCategoryBtn.addClass('loading');
    }, this),
    onEndLoading: $.proxy(function() {
        this.$newCategoryBtn.removeClass('loading');
    }, this),
    onHideHud: $.proxy(function() {
        this.$newCategoryBtn.removeClass('inactive').text(newCategoryBtnText);
    }, this),
    onSaveElement: $.proxy(function(response) {
        // Make sure the right group is selected
        var groupSourceKey = 'group:' + groupId;

        if (this.sourceKey !== groupSourceKey) {
            this.selectSourceByKey(groupSourceKey);
        }

        this.selectElementAfterUpdate(response.id);
        this.updateElements();
    }, this)
});

So it could look like

var button = $('#yourButton');
Craft.createElementEditor('craft\\elements\\Entry', {
    hudTrigger: button ,
    elementType: 'craft\\elements\\Entry',
    siteId: this.siteId,
    attributes: {
        sectionId: 1, // <-- insert your section id here
        typeId: 1 //<-- important, insert your valid type id otherwise it won't work
    },
    onBeginLoading: $.proxy(function() {
        button.addClass('loading');
    }, this),
    onEndLoading: $.proxy(function() {
        button.removeClass('loading');
    }, this),
    onHideHud: $.proxy(function() {
        button.removeClass('inactive').text('New Entry');
    }, this),
    onSaveElement: $.proxy(function(response) {
        // insert the id of the saved element to hidden input
    }, this)
});


Split-style button for "New" custom element I've got a plugin with a custom element. It evolved based on the basics laid out in the P&T Events sample plugin.

On my element's index page, there's a big button to create a "New Element". When you click on it, you see a dropdown list of every available group for the new element:

This is the result generated by the code in the Events example.

However, I really want a split button format, like Craft provides for its entries:

The advantage there would be the "one click" add, if you're already viewing the target group.

I've tried copy & pasting various HTML from the entries template, but that doesn't really seem to be doing the trick. I suspect JS is playing a large role in generating that menu, but I haven't quite figured it out yet.

How can I make a split-style button for my custom element?

Those split-style buttons are just multiple regular buttons (.btn) next to each other, wrapped in a .btngroup div:

  Button One
  Button Two

If you want to make one of your buttons trigger a dropdown menu, give it the class .menubtn, and add your .menu div right after it.

  Button One

Menu Button

Option One

Option Two

As long as this HTML is in the page’s initial HTML, Craft will automatically initialize the menu. If you’re adding it in JavaScript later on, you will need to initialize the menu yourself, by calling the menubtn() jQuery function on it:

$('#mycontainer .menubtn').menubtn();