Craft front-end forms not working with Angularjs app I'm making a site with Craft CMS/Angularjs. I'm using angular to filter and display entries on the index page and it's working good so far except for one thing. The login/register/entry form's all don't function at all. If I remove ng-app from the html tag they work just fine so it's definitely angular that's causing this issue.

Here's my login form on the main page:

{% if currentUser %}
        You are logged in as {{ currentUser.friendlyName }}
        logout

    {% else %}

    <form method="post" action="" accept-charset="UTF-8">
        <input type="hidden" name="action" value="users/login">

Username

        <input id="loginName" type="text" name="loginName">

Password

        <input id="password" type="password" name="password">

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

        {% if errorMessage is defined %}

{{ errorMessage }}

        {% endif %}

Please login or register

    </form>

    {% endif %}

If anyone with experience using angular and craft together can chime in that'll be great.

Okay so I figured it out. Turns out a form won't submit in an Angular app if it doesn't have an action specified.


Multi Country website - Using locales is the best approach? I will work in a website that have presence in 3 countries: Nicaragua, Panama, Costa Rica. They will upload products and want that each country have they own product or product information.

So i think about locales to organize the website, to give 3 different contexts to load information, and the ability to change a existing product for each country.

My question is: this 3 countries speaks Spanish, and i want to clearly show the client which country he is editing- Can i duplicate the Spanish locale and put the country name on each one ( to show PANAMA-COSTARICA-NICARAGUA ) ? I see the list of locales but i don´t know if this 3 countries are available...
Thanks!

Sebastian.

Yes you can do this by going to the craft/app/framework/i18n/data folder and copying the language file for each occurrence.  You must give each a unique name es_pn, es_co, es_nc.  Inside each of those files you must add each of those names along with the long form name.

languages => array(
'es_pn' => 'Panama',
'es_co' => 'Costarica',
'en_nc' => 'Nicaragua',

From here you would select each of those locales from the CP and setup the rest of your site as you would for multiple locales, using your custom ones. Updates have currently never broken this.  We have been using this method for several clients, it works well.


Contact Form Setup on Craft CMS I am just getting to grips with Craft CMS and am finding the Contact Form plugin tricky to use. I have built a reasonable site structure, figured how fields, sections, etc work at a relatively basic level and have produced a one-for-all template so far in the templates/ root folder. But the form eludes me.

I have added the contact form example from https://github.com/craftcms/contact-form to the main template at present, and this shows on my /contact/ page. However, the submission of the form returns an error as follows:

Template not found: contact/thanks

I would assume I need to make a section/entry for the contact/thanks page? So I have now done that. The form submits but just goes to a blank page at contact/thanks even though I have created content on that entry. It's not drawing any of the data items specified in the Twig template.

It also does not send an email. I have implemented and tested the Settings > Email webserver details successfully. But all submissions are being collated in the "Form Submissions" area (Contat Form Extensions plugin).

I note that the form has no action, but the hidden field below exists:

<input type="hidden" name="action" value="contact-form/send">

Do I need to create a page for contact-form/send too? I have clearly made the naive assumption that the plugin would sort the sendmail part but some action is required on my part.

Sorry, I'm a noob. Guidance appreciated.

Without an entry with slug contact/thanks then the page just returns an error Variable "entry" does not exist. But still it doesn't draw any content from the entry.

You do not need to create an entry for the Thanks page - in most cases it is easier to just add the actual text to your template file. If you do want to make it editable, then create a Single Entry, name it whatever you want, then go to Settings > Sections > yourSection and edit the uri and path variables. The URI should be contact/thanks, and the template path would likely be something like thanks.html


Problem with @font-face url 500 server error craft style So not sure what the problem is really have tried a few ways but I can't get font-files to work.

I have placed my font files in

 root/craft/templates/assets/fonts/bootstrap

Here is an example of @font-face that I am using...

@font-face {
    font-family: "Glyphicons Halflings";
    src:
    url("{{ siteUrl }}/assets/fonts/bootstrap/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"),
    url("{{ siteUrl }}/assets/fonts/bootstrap/glyphicons-halflings-regular.woff2") format("woff2"),
    url("{{ siteUrl }}/assets/fonts/bootstrap/glyphicons-halflings-regular.woff") format("woff"),
    url("{{ siteUrl }}/assets/fonts/bootstrap/glyphicons-halflings-regular.ttf") format("truetype"),
    url("{{ siteUrl }}/assets/fonts/bootstrap/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg");
}

In firebug I get "NetworkError: 500 Internal Server Error - http://example.com/assets/fonts/bootstrap/glyphicons-halflings-regular.woff"

If I try to access the file directly I get the following message with craft styling etc so this is a craft error not a typical 500 error.

Internal Server Error

Unexpected character ""

Now if I try to access a css file it works fine, but my font files are returning 500 errors.

I have placed my css files in

 root/craft/templates/assets/css

Your css and your fonts should be in the public section of the craft website. So put your css in "root/public/assets/css" and "root/public/assets/fonts/bootstrap". Than remove the {{ siteurl }} twig code (in this therme only use plain css).


Using “search” vs. “relatedTo” in a template I have problems to understand the difference between search and relatedTo. From my understanding, this is a fulltext search on all fields.

{% set entries = craft.entries.search(test).order('score') %}

Does the following approach mean the same?

{% set entries = craft.entries.relatedTo(test).order('score').find() %}

And if yes, which one delivers the better performance?

Thanks!

To be honest, those two parameters may seem to be slightly similar but provide a totally different functionality.
From their documentation on search:

search
Only fetch entries that match a given search query. (See Searching for the syntax and > available search attributes.)

Which means whatever you pass in .search(query), and there is a rather complex list here, will actually 'search' Craft for the query string you specify.
On a different note,

relatedTo
Only fetch entries that are related to certain other elements. (See
Relations for the syntax options.)

This on the other hand only 'relates' to other entries, meaning its not performing a fill search on Craft, only the entries. A detailed reference on relations can be found here.
As far as performance, the two are unrelated as it really depends on what you are trying to accomplish.
Hope this clears it up for you!


Disable image cleansing for public facing form uploads We want the public uploads to remain in raw state. Is it possible to disable image cleansing for entries created through public facing form? (Image cleansing to continue working for uploads through Control Panel.)

The imageDriver setting just determines which driver Craft should use when working with images (GD or ImageMagick) for things like image cleansing and image transforms. So changing its value will not affect whether images are cleansed on upload; just which driver would be used for that process.

If you want to disable image cleansing on the front end, you will need to write a plugin that handles the upload. You can find out how to do that from this answer: https://craftcms.stackexchange.com/a/9675/9


How to modify the login panel how can i modify the login html?
I specifically want to add an image below the title.

You can add a logo to the login page by uploading one to Settings → General Login Page Logo.
If you need further tweaking, you could use the Control Panel CSS plugin.
I wouldn't recommend modifying Craft's templates.


Returning a "is currently unable to handle this request. 500 Error" when client posts I'm working with a client to resolve an issue that has appeared recently with a Craft site. Up until recently there were no issues with the site for my client, but she is now getting a 500 Error:

  site.com is currently unable to handle this request. HTTP ERROR 500

This happens whenever my client tried to create a new entry post. Uploading an image is okay, but posting is not. We're running Craft 1.3.2487.

Any help or direction on this would be greatly appreciated.

As Lindsey pointed out, I'd also highly recommend taking some time to update to the latest Craft release. Craft 1.3 is over 3 years old now.

If you're getting a 500 Internal Server Error, then it's either being generated by Craft or by your web server.

If it's generated by Craft, it will be Craft styled and the underlying error message will be in your craft/storage/runtime/logs folder.

If it's generated by your web server, the underlying error message should be in your web server's error logs.


FeedMe plugin broke Craft I was using the FeedMe plugin engram-design to move my podcast xml items to entries in a podcast section I tried running a task to update some entries and it broke my site. Now I am unable to access the admin portion of my site. I receive the following error.

Fatal error: Class 'Craft\FeedMe_FeedModel' not found in /www/sites/mywebsite/craft/app/helpers/ModelHelper.php on line 587

I've tried replacing the app folder with a fresh copy, but nothing. Any suggestions?

You'll be able to get better/quicker help through the plugin page and submitting an issue - https://github.com/engram-design/FeedMe/issues. I'd be happy to help and see what might be the issue.

But if you could, please follow the Support steps as outlined here - https://github.com/engram-design/FeedMe#support.


How to get section content from another site with multisite setting I have a multisite on Craft 3 and I was wondering how to get section content from another site? Let's say I'm on a default site and I want to get contact content from site with handle siteA?

Can this be done?

From a template you could do:

{% set entries = craft.entries.section('jobs').site('siteA').all() %}

In your follow up comment, you're passing craft.entries as an element to relatedTo, but that's just going to be an instance of the ElementQuery class.  You need to give it the actual element you're interested in finding the relationship to.


Creating forms that save to the database & can be viewed in the admin is it possible to create forms that save to the DB & a new screen in admin to see the submissions?

Is there a user created forms module (like gravity forms) for Craft?

For now, you can create forms and create entries through the plugin Guest Entries.

In Guest Entries, entries are disabled by default.

Sprout also has a plugin for creating forms, that is currently in beta.

Is there anything specific you are looking for, or would you just like to be able to receive submissions from site users?

If you give some more information, we might be able to give you some better advice, but the Forms Market is still pretty thin.

Would you say those forms are always the same in the context of a site? You don't need a form builder for that (?), unless they are always changing and adding things. Even then, you can make a rudimentary form builder by using Matrix.

The notifications part has to be be added by a custom plugin. You can hook into the onSaveEntry hook, for example.

I built a notification plugin that does that, which sends of an e-mail and a sms to the site owner when entries are added through Guest Entries.

Subscribing to MailChimp is also fairly easy. You can have a look at the MailChimp Subscribe plugin as an example.


Modify ElementCriteria and use it for paginate First some context. I'm using Smart Map for Craft to display some location based events in a listing. My structure is as follows:

Events channel
Locations channel

Each event can occur multiple times, so I created a matrix field for this, where they can add blocks with a time and select a location.
The problem occurs when I want to filter the list of results based on the city of the location. Smartmaps doesn't support filtering by cities and I do want to use pagination, so I went with the custom plugin solution mentioned in that question. Unfortunately I can't comment yet on that answer, so therefore I created my new question.
The problem is that Craft {% paginate %} doesn't work with the Array result of EntryModel::populateModels. I'm getting the following error in my search results page:

Argument 1 passed to Craft\TemplateHelper::paginateCriteria() must be an instance of Craft\ElementCriteriaModel, array given

So my question is, how can I modify the ElementCriteriaModel to join content from different tables (in this case Smartmaps') and still return an ElementCriteriaModel to be used by the Craft pagination?
I also have read some more explanation about ElementCriteriaModel and some similar issues like this one and this one, but without any luck. Maybe there is a much simpler solution, but I'm out of options for now.

You can only modify a craft.entries criteria model with a field (→ Add custom element criteria attribute without a field type?). So what you have to do is to create a new custom field type with your plugin, and add such a field to the entry types you want to filter.

{% set entries = craft.entries.section('mySection').country('germany') %}

With that criteria model you would pass the value "germany" to your custom field type field "country". The field type would then use this parameter to modify criteria model's query.

Here's some code that should help you putting this together:

public function getInputHtml($name, $value)
{
    return;
}

public function modifyElementsQuery(DbCommand $query, $params)
{
    if ($params !== null)
    {
        craft()->businessLogic->addCountryCriteria($query, $params);
    }
}

You don't want the field to show up as an input field in the edit entry view, so we let getInputHtml() return null.

In our modifyElementsQuery method we just check if there's a parameter submitted (the country), before passing the criteria model's query to the service.

public function addCountryCriteria(DbCommand $query, $country)
{
    // Add conditons to the query
    $query->andWhere($conditions, $params);
}

Your addCountryCriteria service can basically stay untouched, except that you can remove buildElementsQuery(), queryAll() and populateModels(). As you only want to modify the query.


All images uploading... except JPG files No idea why but my local install of CraftCMS (in a MAMP environment) won't let me upload JPGs. PNG, GIF, even TIFF works (just for the heck of it). When I select the file in the browser dialog, it closes then shows the loader bar and spinning gif anim. No progress is ever shown and the spinning continues eternally. http://cl.ly/image/1a2l1W2t1P1x

Craft is up to date
Uploads on remote install works perfectly
Getting this error net::ERR_EMPTY_RESPONSE along with these details: http://cl.ly/image/3D2w1F2l2O1x
Checked my php.ini file and it allows JPG uploads

I realize this may not even be an issue with Craft but a server side issue. I just have no idea how to troubleshoot this. Any help would be much appreciated!

I also checked my phperrors.log file and I got only this which is from back in early Dec and seemingly unrelated.

  [08-Dec-2014 02:47:37 UTC] PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 9792 bytes) in /Applications/MAMP/htdocs/sucasa/craft/app/vendor/imagine/imagine/lib/Imagine/Gd/Image.php on line 199

I had this same issue and resolved it (at the suggestion of Craft CMS support) by enabling ImageMagick in the php.ini and restarting MAMP PRO.

Per the MAMP PRO 3.0 user guide:

The ImageMagick PHP module is included by default, but you must enable it inside the php.ini template file. Remove the ‘;’ from the following line.
;extension=imagick.so


How can i get all values in a global set I would like to get all the fields (with their handles and values) for a given global set.

For example : My set is called 'labels'.
I know I can get the set by using :

$criteria = craft()->elements->getCriteria(ElementType::GlobalSet);
$criteria->handle = 'labels';
$labels = $criteria->first();

Or with :

$labels = craft()->globals->getSetByHandle('labels');

Then I can get a specific data with

$labels->myDataHandle

But how can I get all the data/fields in the set ?
I would like to have an array or an object with all my labels (in my controller I return the value using returnJson).

Thanks for your help !

Have a look at the answer given here to someone trying to solve this in the template. With a plugin you'd probably do it like so:

public function getFieldsByEntry($entryModel)
{
    $fields = array();
    $fieldLayoutFields = $entryModel->getFieldLayout()->getFields();
    foreach ($fieldLayoutFields as $fieldLayoutField)
    {
        $fields[] = craft()->fields->getFieldById($fieldLayoutField->fieldId);
    }
    return $fields;
}


Update Global Variables I've got a custom plugin where I'm trying to update a global variable. The variable field type is of type Entry

I'm getting the set using getSetByHandle then using getContent on the set. However, when I do a count on the retrieved content, the value is 1. I have about 10 global variables so would've expected a count of 10.

I'm clearly doing something wrong, so a nudge in the right direction would be appreciated.

Update

Here's the code I'm currently using

$global_set = craft()->globals->getSetByHandle('globalVariables');
$selected_poll = craft()->entries->getEntryById($poll_id);
$content = $global_set->getContent();
craft()->globals->saveSet($globalSet);

Update

I've also tried the following, with no luck:

$globalSet = craft()->globals->getSetByHandle('tempSet');
$content = $globalSet->getContent();
$content->currentItem = craft()->entries->getEntryById($itemID);
$globalSet->setContent($content);
craft()->globals->saveContent($globalSet);

Ok figured it out. I was going about it completely the wrong way. As the field in question is an Entry type, I needed to use the Relations Service

$globalSet = craft()->globals->getSetByHandle('[globalSetHAndle]');
$selectedField = craft()->fields->getFieldByHandle('[fieldHandle]');
craft()->relations->saveRelations($selectedField, $globalSet, array($entryId));

Passing null instead of array($entryId) will clear the relation values


Venti Events causing failed DeleteStaleTemplateCaches task As you can see from the craft.log, venti is causing an issue with template refresh:

2016/01/19 10:59:27 [info] [application] [Forced] Starting step 242 of 828 total steps.

2016/01/19 10:59:27 [info] [application] [Forced] Starting step 243 of 828 total steps.

2016/01/19 10:59:27 [error] [system.db.CDbCommand] CDbCommand::fetchAll() failed: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'venti.startDate' in 'order clause'. The SQL statement executed was: SELECT `elements`.`id`, `entries`.`sectionId`, `entries`.`typeId`, `entries`.`authorId`, `entries`.`postDate`, `entries`.`expiryDate`

FROM `craft_elements` `elements`

JOIN `craft_elements_i18n` `elements_i18n` ON elements_i18n.elementId = elements.id

JOIN `craft_content` `content` ON content.elementId = elements.id

JOIN `craft_entries` `entries` ON entries.id = elements.id

JOIN `craft_sections` `sections` ON sections.id = entries.sectionId

LEFT JOIN `craft_structures` `structures` ON structures.id = sections.structureId

WHERE (((elements_i18n.locale = :locale) AND (content.locale = :locale)) AND (elements.archived = 0)) AND (elements_i18n.enabled = 1)

GROUP BY `elements`.`id`

ORDER BY `venti`.`startDate` ASC LIMIT 5.

2016/01/19 10:59:27 [error] [application] Encountered an error running task 5 (DeleteStaleTemplateCaches), step 243 of 828: An exception was thrown: CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'venti.startDate' in 'order clause'

Has anybody else had this issue? Frustrating as it means my cache isn't working properly, causing 'Failed Task' to show up in the Admin for the client and I'm not sure but may be affecting other areas of the site.

Thanks in advance.

0.9.14 is still the beta version.  Go into the Venti_EventManageService file and delete the two lines with this string craft()->templateCache->deleteCachesByElement($element);.


Any alternative to Dukt Analytics? I am unable to pay $99 for Dukt Analytics. Does anyone know of a free alternative that gives me google analytics stats for the dashboard?

https://straightupcraft.com/craft-plugins/?q=analytics& shows some possible analytics candidates.

Particularly these:

https://straightupcraft.com/craft-plugins/instant-analytics

https://straightupcraft.com/craft-plugins/piwik-analytics

https://straightupcraft.com/craft-plugins/3redkites-piwik-analytics-for-craft-cms

https://straightupcraft.com/craft-plugins/tracker


Using the Guest Entries plugin, how can I allow people to edit/delete? I have a form for people offering or requesting to share-a-lift to an event.
I'm using the Guest Entries plugin.

But I need them to be able to edit and delete those entries, as once a pair are matched up they need removing from the list of offers/requests to avoid multiple offers.

I have a page with the list of the lifts on offer or requested and have a link from each of the entries to the form page but with the entryId as segment 2.

How do I code the Delete button? (turns out you can't)

I appreciate that this is not the most secure way of doing things, but the client has been using a similar form/method on their old site and have not had any fraudulent or malicious issues in many years.
If anyone can suggest a more secure method without any logins or registration I'm open to ideas.

The final solution

As you can't delete or edit Guest Entries @carlcs came up with the idea of allowing a second entry (in another entry type) with a common field to the first.

In the template listing all the offers and requests you look for entries from both entry types with a matching field, and if a match is found don't show either. See the code in his answer for the details.

What you could try is to use the Preparse plugin and add a field to your entry type that automatically generates a secret key for each submitted entry.

Show the user this key on the page they are redirected to upon form submission, tell them to write it down.

You now set up a new guest entry form to submit matches. So instead of deleting entries, the user enters his personal secret key into a field to submit a new entry (I'd suggest to post to the same channel but different entry type).

On the front-end you can now list only those requests/offers entries that do not have a matching "delete" entry yet. Another advantage over your delete approach is that you have a nice record and overview in the CP of what was offered and when.

Code example:

There's no template function to generate a random string, but you could apply Craft's shuffle function on an array of characters.

{%- set chars = '012345678901234567890123456789'|split('') %}
{%- set key = shuffle(chars)|join %}

{{- key|slice(0, 6) }}

That's how you could generate the secret keys within the Preparse field. And to loop through your "requests" and only show them if there's no matching "response" entry yet, do something like this.

{% set requests = craft.entries({
    section: 'lifts',
    type: 'requests',
    limit: null,
}) %}

{#
 # Loop through all "requests". Check for each of them if there's a
 # matching "response" before outputting.
 #}
{% for request in requests %}

    {#
     # Try to get an entry of entry type "responses" where the "secretKey"
     # field value matches the "secretKey" of the "request" in the current
     # itteration of this "requests" loop (returns an EntryModel or NULL).
     #}
    {% set hasResponse = craft.entries({
        section: 'lifts',
        type: 'responses',
        secretKey: request.secretKey,
    }).first() %}

    {#
     # Only output if "hasResponse" is not NULL
     #}
    {% if not hasResponse %}
        {{ request.message }}
    {% endif %}
{% endfor %}


Update Asset Indexes gives "getFileList() is not implemented" Thank you in advance for any tips on this.

Barely-related-background: I made a mistake on my development machine. In gparted, I chose "ignore" instead of "cancel". This is called 'choosing poorly'. Anyway, I now have freshly reinstalled my OS, apache, php, etc.

Now, as the title says, when I click "Update Asset Indexes" it gives a popup saying getFileList() is not implemented

Any suggestions what I need to do?

This exception in thrown in the class craft\volumes\MissingVolume that states one of your Volumes has an invalid class

/**
 * @inheritdoc
 */
public function getFileList(string $directory, bool $recursive): array
{
    throw new NotSupportedException('getFileList() is not implemented.');
}

Maybe you uninstalled a plugin that adds a certain Volume class like S3 or something?


Image upload failed- file not writable Trying to upload images and get the following error

Upload failed for "filename". The error message was "Error uploading the file: The folder "/var/www/html/imgs/logos/" is not writable"

On the server, check:

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

Within Craft:

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

imgs/logos/


What are the different scenarios to plan for when using $allowAnonymous in a controller? Craft 3.2 updates how the allowAnonymous behavior works. I have things working in our plugins but I don't understand the different syntaxes needed across our different allowAnonymous use cases.

For example, Sprout Forms fails to submit unless we update the action to use the new self::ALLOW_ANONYMOUS_LIVE setting. However, Sprout SEO XML Sitemaps work fine without any updates. When I look through Craft I see some methods using the conventions (install controller, preview controller) and others not using any new conventions (generate thumb, live preview controller)

In one case, the Sprout Address Field controller, the prefix action- seems to matter now and removing it alone, gets things updated and working again:

// Failure while logged out
protected $allowAnonymous = [
    'action-update-address-form-html'
];

// Success while logged out
protected $allowAnonymous = [
    'update-address-form-html'
];

// Success while logged out
protected $allowAnonymous = [
    'update-address-form-html' => self::ALLOW_ANONYMOUS_LIVE
];

The general question is: what has been updated with the allowAnonymous behavior in Craft 3.2 and what scenarios does it require that we use the additional configuration settings such as ALLOW_ANONYMOUS_LIVE and ALLOW_ANONYMOUS_OFFLINE?

Here are the new constants that Craft 3.2 introduced:

const ALLOW_ANONYMOUS_NEVER = 0;
const ALLOW_ANONYMOUS_LIVE = 1;
const ALLOW_ANONYMOUS_OFFLINE = 2;

By default every controller will have the following property:

protected $allowAnonymous = self::ALLOW_ANONYMOUS_NEVER;

And you can override it in your controller in various ways:

// Allow anonymous access to all actions only when the site is live
public $allowAnonymous = true;

// Allow anonymous access to the `preview` action only when the site is live
public $allowAnonymous = ['preview'];

// Allow anonymous access to the `preview` action only when the site is live
public $allowAnonymous = ['preview' => self::ALLOW_ANONYMOUS_LIVE];

// Allow anonymous access to the `preview` action only when the site is offline
public $allowAnonymous = ['preview' => self::ALLOW_ANONYMOUS_OFFLINE];

// Allow anonymous access to the `preview` action when the site is live or offline
public $allowAnonymous = ['preview' => self::ALLOW_ANONYMOUS_LIVE | self::ALLOW_ANONYMOUS_OFFLINE];

The single pipeline | is a bitwise OR operator. It compares each bit (a binary digit of 0 or 1) in the integers and returns a new integer with a 1 wherever either numbers had a 1, and a 0 anywhere else (similar to how the || operator campares booleans). So the expression self::ALLOW_ANONYMOUS_LIVE | self::ALLOW_ANONYMOUS_OFFLINE is the same as 1 | 2 and will evaluate to 3. Here are some examples of how the | bitwise operator works:

( 0 = 0000) | ( 0 = 0000) => ( 0 = 0000)
( 0 = 0000) | ( 1 = 0001) => ( 1 = 0001)
( 0 = 0000) | ( 2 = 0010) => ( 2 = 0010)
( 1 = 0001) | ( 1 = 0001) => ( 1 = 0001)
( 1 = 0001) | ( 2 = 0010) => ( 3 = 0011)
( 2 = 0010) | ( 2 = 0010) => ( 2 = 0010)

The init() method of the Craft base controller now normalizes the value as follows:

// Normalize $allowAnonymous
if (is_bool($this->allowAnonymous)) {
    $this->allowAnonymous = (int)$this->allowAnonymous;
} else if (is_array($this->allowAnonymous)) {
    $normalized = [];
    foreach ($this->allowAnonymous as $k => $v) {
        if (
            (is_int($k) && !is_string($v)) ||
            (is_string($k) && !is_int($v))
        ) {
            throw new InvalidArgumentException("Invalid \$allowAnonymous value for key \"{$k}\"");
        }
        if (is_int($k)) {
            $normalized[$v] = self::ALLOW_ANONYMOUS_LIVE;
        } else {
            $normalized[$k] = $v;
        }
    }
    $this->allowAnonymous = $normalized;
} else if (!is_int($this->allowAnonymous)) {
    throw new InvalidConfigException('Invalid $allowAnonymous value');
}

Source: https://github.com/craftcms/cms/blob/3.2.2/src/web/Controller.php#L75-L96

So if the value is a boolean then false will be normalized to 0, whereas true will be normalized to 1.

If the value is an array then each key-value pair in the array will be inspected. If the key is an integer then the value is set to 1, for example:

public $allowAnonymous = ['preview'];

equates to

public $allowAnonymous = [0 => 'preview'];

and is interpreted as

public $allowAnonymous = ['preview' => self::ALLOW_ANONYMOUS_LIVE];

If the key is a not an integer then the key-value pair is left as is.

Here is how $allowAnonymous is enforced:

// Enforce $allowAnonymous
$isLive = Craft::$app->getIsLive();
$test = $isLive ? self::ALLOW_ANONYMOUS_LIVE : self::ALLOW_ANONYMOUS_OFFLINE;

if (is_int($this->allowAnonymous)) {
    $allowAnonymous = $this->allowAnonymous;
} else {
    $allowAnonymous = $this->allowAnonymous[$action->id] ?? self::ALLOW_ANONYMOUS_NEVER;
}

if (!($test & $allowAnonymous)) {
    // Prevent access unless the user is logged in and has the required permissions to view the site
}

Source: https://github.com/craftcms/cms/blob/3.2.2/src/web/Controller.php#L147-L176

The single ampersand & is a bitwise AND operator. It compares each bit in the integers and returns a new integer with a 1 wherever both numbers have a 1, and a 0 anywhere else (similar to how the && operator campares booleans). Here are some examples of how the & bitwise operator works:

( 0 = 0000) & ( 0 = 0000) => ( 0 = 0000) => false
( 0 = 0000) & ( 1 = 0001) => ( 0 = 0000) => false
( 0 = 0000) & ( 2 = 0010) => ( 0 = 0000) => false
( 1 = 0001) & ( 1 = 0001) => ( 1 = 0001) => true
( 1 = 0001) & ( 2 = 0010) => ( 0 = 0000) => false
( 2 = 0010) & ( 2 = 0010) => ( 2 = 0010) => true
( 3 = 0011) & ( 1 = 0001) => ( 1 = 0001) => true
( 3 = 0011) & ( 2 = 0010) => ( 2 = 0010) => true
( 3 = 0011) & ( 3 = 0011) => ( 3 = 0011) => true

By enforcing the condition $test & $allowAnonymous, we can check that $test (whether the site is live or offline) and $allowAnonymous (the permissions granted to the specific controller action) overlap.

More on bitwise operators here.

I'm not sure what the specific issue with your plugin is , but as far as I can tell the only thing that changed in Craft 3.2 was that the ALLOW_ANONYMOUS_OFFLINE constant was added, allowing for (but not requiring) more specific permissions on controller actions.


Search for Matrix Block by Date in plugin I am trying to search for specific matrix blocks by date like so:

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

$criteria->ownerId = $entry->id;

$criteria->type = 'myMatrixBlockType';

$criteria->myMatrixBlockDateField = "2016-06-01 04:00:00";

$criteria->limit = 10;

$blocks = $criteria->find();

It seems that no matter what format the date is, all blocks from the matrix field in the entry are returned. Any help is appreciated!

You need to add a fieldId param to make Craft join the content table.

$criteria->fieldId = $matrixFieldId;


Contact Form plugin - different recipients per locale What is the best way to define different sendto emails addresses for the ContactForm plugin, depending on the locale the site is currently viewed in?

I am setting up a multilanguage site, and the clients want to have different emails for each language version.

So far I figure a possible way would be to have separate, localized contactform templates, and in each of them define a dynamically-added recipient. But I wondered if there's a better option, e.g. locale-specific options in craft/config/contactform.php?

Thank you

You could write a plugin, which hooks in the contact form's onBeforeSend event, and modifies the recipients.

Here's an absolute bare-bones solution which does exactly that (not tested in any way whatsoever):

<?php namespace Craft;

class ExamplePlugin extends BasePlugin
{
    // Standard plugin methods omitted for brevity...

    public function init()
    {
        craft()->on('contactform.beforeSend', function (Event &$event) {
            $event->toEmail = 'john@doe.com';
        });
    }
}

Whether or not this is "officially" supported is unclear.

The fact it's an event (as opposed to a hook) might suggest not, but the contact form does check whether any listeners modified the event data, as evidenced by its check of the isValid property.


Caching and TTFB with Craft I've just launched my new site here and I'm playing around with the caching options with Craft. I'm hosting my site with Siteground which gives me access to their Supercacher option, it offers Static cache and Memcached, both of which I have enabled.

I have configured Craft to use Memcached via the general.php config file 'cacheMethod' => 'memcache' and placed the memcache.php file into the config directory as well with 'useMemcached' => true, set to true and my host to 'host' => 127.0.0.1, plus the correct port that is provided by my host. I've also got Cloudflare CDN running which is taking care of a lot of the heavy lifting.

I've also wrapped {% cache %} tags around the mainly static content.

However I'm still left feeling slightly uneasy about my TTFB and site performance, so I have some questions:

Should the IP address for 'host' in memcache.php be wrapped with quotes? I saw "localhost" was in the default file but typically IP addresses are not, so I didn't
My TTFB has been wildly inconsistent, ranging anywhere between 200ms up to 2s. What is the best way to troubleshoot such an issue with Craft? Or is this more of a host issue?
I'm using AJAX page transitions based off this article: https://designbycosmic.com/journal/craft-cms-ajax-page-transitions-with-history-pushstate - could this be messing things up?

I appreciate any feedback or pointers people may offer because I'm feeling a little lost/overwhelmed at the moment. cheers!

This isn't an issue with Craft, from the POV that the TTFB should be pretty consistent.  How are you testing it?

My guess would be that the issue is with your hosting. These two articles may help you:

The Craft {% cache %} Tag In-Depth

A Pretty Website Isn't Enough

Run some of the diagnostic tests listed in the second article.


Discount Code applies to cart successfully but doesn't do anything. Am I missing something? Standard 10 dollars off discount setup.  Although it says it is applied, it doesn't give me any kind of a discount.  None of the discounts work, I've made multiple and tried different options but it still doesn't work.  Any ideas?

The reason for the discount not being applied is that nearly all your products have not been marked as promotable (by looking at your database):

Screenshot: http://jmp.sh/3FAK6NH

No sales or discounts can be applied to a non-promotable product.


$event->performAction = false; doesn't stop action I've got a plugin which creates an entry on user activation. I'm trying to extend the plugin so that after public registration the account is not activated (i.e., force an Admin to activate the account).

According to the documentation I'd expect this code block to stop activation:

public function init() {
    craft()->on('users.beforeActivateUser', function(Event $event){
        // stop the user from being able to activate their account. Forces admins to do so.
        //if($event->params['user']->isInGroup('artists')){
            $event->performAction = false;
        //}
    });
}

But it doesn't. What am I doing wrong? Full plugin code here: https://gist.github.com/MattWilcox/1549fb9d5787288b3b84

Turns out this was a bug in Craft that's been fixed for the next (post 2.3.2629) release.


How to get Category URL from field in Matrix This is my Matrix set up:

I'm stumped to how to get the Categories URL.

{% for block in entry.galleriesItem %}
    {% switch block.type %}

        {% case "galleriesItem" %}

                    {% for asset in block.image %}

                    {% endfor %}

                        {{ block.galleryType }}

    {% endswitch %}
{% endfor %}

I previously used:

{{ block.linkTo.first().url() }}

when the field type was an entry.

{{ block.linkTo.first().url() }} looks basically right, but a couple of things could be going wrong here:

Does the Galleries category have a url assigned? (make sure the "Categories in this group have their own URLs" box is checked)
Is there a category? You should always check, even if it is a required field. You can do {% if block.linkTo.first() %}...{% endif %} or {{ block.linkTo.first().url() ?? '' }} and use the A null coalescing operator.


Adding Columns to a table Is there a way or a plugin that allows you to add columns and change columns heading from within the entry? Instead of defining column heading while creating the table field. It would be nice to have the ability to add/delete columns and have the table be dynamic.

With the supercool table maker you can create dynamic tables. Is this what you are looking for?


Craft 3 - Moving assets between folders causes apache connection to max out In Craft 3, I keep running into an issue when I try to move a large amount of files (around 200) by dragging and dropping from my “Holding” folder into a “Live” folder using Craft Assets section. Both folders are hosted on Amazon S3.  Even moving three files seems to take a really long time (about a minute).

After checking the server logs it looks like I am filling my max apache connection due to the search-index-perform-action.  The error suggested I increase my “MaxRequestWorkers” setting.

I move about 2,000 files every month and never had a problem on Craft 2.  I don’t know if should change the “MaxRequestWorkers” setting or if there is something else I should consider doing.  If I should change the setting, where is it, I can't seem to find it.

I use Transmit FTP to initially move the files into the Holding folder and then index the assets in that folder. Then in Craft CMS control panel, I drag the files from Holding folder to the main Live folder so that the asset index gets updated.

UPDATE

I looked in my phperror.log file and found these three types of errors occuring:

PHP Fatal error:  Allowed memory size of 268435456 bytes exhausted (tried to allocate 1048576 bytes) in /storage/avxxxxx/www/public_html/vendor/craftcms/cms/src/helpers/DateTimeHelper.php on line 231

PHP Fatal error:  Allowed memory size of 268435456 bytes exhausted (tried to allocate 20480 bytes) in /storage/avxxxxx/www/public_html/vendor/craftcms/cms/src/elements/db/ElementQuery.php on line 2215

PHP Fatal error:  Maximum execution time of 90 seconds exceeded in /storage/avxxxxx/www/public_html/vendor/league/flysystem/src/Util.php on line 322

PHP Fatal error:  Maximum execution time of 90 seconds exceeded in /storage/avxxxxx/www/public_html/vendor/league/flysystem-aws-s3-v3/src/AwsS3Adapter.php on line 294

PHP Fatal error:  Maximum execution time of 90 seconds exceeded in /storage/avxxxxx/www/public_html/vendor/league/flysystem/src/Util/ContentListingFormatter.php on line 52

It seems like when I move a file from Holding (950 files) to Live (20,000) files is where things get hung up.

Holding -> Live = 1 file takes 7 seconds to move
Live -> Holding = 1 file takes 20 seconds to move

Could it be an issue with the cache or search-index?

Here are my current settings if it helps:

memory_limit 256M

max_execution_time = 90

Max Requests = Per Child: 300 - Keep Alive: on - Max Per Connection: 150

Timeouts = Connection: 10 - Keep-Alive: 2

I would remove the overhead of the CMS all together by using an app like Filezilla, Cyberduck or similar app to move files. There are plenty of tutorials out there on how to connect to an S3 bucket using one of these apps (eg. https://stackoverflow.com/questions/45293159/how-to-setup-filezilla-pro-to-access-to-my-s3-bucket)

After you do this you will most likely need to update your asset indexes in the control panel:

Utilities → Asset Indexes (or Settings → Update Asset Indexes if you're on Craft 2)


User group discount not applied when user has existing cart I've run accross an issue that seems like a bug to me and I'm desperately looking for some help to solve it.

I've created user groups in Craft & Discounts applicable to those user groups in Craft Commerce.

a user lands on the site and adds items to his cart & proceeds to checkout
the user is prompted to login or register
the user logs in OR registers
3a. upon registration the user is activated & auto logged in with the 'autoLoginAfterAccountActivation' => true config option
the user is redirected back to his cart - at this point in time I'm expecting to see a discount adjustment on the cart

The problem is that there is no discount adjustment on the cart - the only way the discount adjustment kicks in is if the cart is updated, by adding or removing an item ie: updateCart is fired.

I've double checked my discount rules & they are definitely setup correctly - the problem is that the users cart is "remembered" from before he was registered ie: before he was part of a user group that is eligible for a discount.

I'm looking for a way to "force" a cart refresh of some sorts.

I have confirmed this would indeed appear to be a bug in Commerce.

A quick workaround would be to listen to login events and call some sort of update cart hack, but this is really a fix that should happen at the Commerce end of things.

I'll report it.

EDIT: Luke Holder comfirms he's found the bug and it will be fixed in the next point release coming soon.


Error when using if statement in template I have a page that shows all photos in a category, which is set by the last url segment  and then the results re paginated. What i'm trying to do is say that if the last segment is 'all' then show all photos from all categories. So i'm trying the following code, but getting an error and i cannot see why!

Template Code:

{% set categoryName = craft.request.lastSegment %}
{% if categoryName == 'all' %}
    {% paginate craft.entries.section('photo').limit(6) as entries %}
{% else %}
{% set category = craft.categories.slug(categoryName) %}
    {% paginate craft.entries.section('photo').relatedTo(category).limit(6) as entries %}
{% endif %}

Craft error:

Internal Server Error

Unexpected tag name "else" (expecting closing tag for the "paginate" tag defined near line 12)

Line 12 is {% else %}, btw.

I have the endPaginate code further down the page after the pagination html, like so:

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

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

{% endpaginate %}

It is expecting an {% endpaginate %}.

{% set categoryName = craft.request.lastSegment %}
{% if categoryName == 'all' %}
    {% paginate craft.entries.section('photo').limit(6) as entries %}
    ...
    {% endpaginate %}
{% else %}
    {% set category = craft.categories.slug(categoryName) %}
    {% paginate craft.entries.section('photo').relatedTo(category).limit(6) as entries %}
    ...
    {% endpaginate %}
{% endif %}

Update: if you want to define the paginate block separately to keep your code dry you can assign the element criteria model to a variable first. See carlcs' answer above/below for another way to do the same.

{% set categoryName = craft.request.lastSegment %}
{% if categoryName == 'all' %}
    {% set ecm = craft.entries.section('photo').limit(6) %}
{% else %}
    {% set category = craft.categories.slug(categoryName) %}
    {% set ecm = craft.entries.section('photo').relatedTo(category).limit(6) %}
{% endif %}

{% paginate ecm as entries %}
    ...
{% endpaginate %}


Running Craft with Docker (or something similar) Has anyone had success with setting up Craft using Docker?

I've stumbled across some Dockerfiles for WordPress and other CMS's but couldn't find much in the way of Craft. I'll be exploring this a bit myself over the next week, but was hoping some people in the community may have a few good pointers or tips or even cautions.

To elaborate, I'm looking for alternatives to MAMP as well, or other development environment tools for working with Craft.

I am creating an image to help me test Craft.

https://github.com/gabrielmoreira/docker-craft


Exclude entries by array of authors from ElementCriteriaModel I'm trying to get a list of entries of a certain section, however I'd like to exclude certain users that are defined within a field of the entry.

The users to exclude from the query are fetched like so:

{% set exclude_users = entry.winners_exclude %}

Now, what I'm trying to do is to exclude the users in theexclude_users-array from being returned with the query results, something like the following (which does obviously not work, but you might get the idea of what I'm trying:

{% for entry in craft.entries.section('bildupload').author(not in exclude_users).search('challengeId:' ~ch.id).order('likecounter desc').limit(3).with(['useruploads']) %}

Specifically I'm talking about the .author(not in exclude_users) part.

I didn't really find anything on the question if that is at all possible within the elementCriteriaModel query itself. It works with an additional if-condition within the for-loop, however since the elementCriteriaModel needs to be .limit(ed) to 3 but needs to exclude some users, excluding them within the loop after limiting the result to the first 3 results obviously results not in what I want, since it will just exclude the users from the first 3 results.

Iterating on Michael's answer: build an array of users to exclude, like this:

{% set excludeArray = null %}
{% for user in entry.winners_exclude %}
    {% if loop.first %}{% set excludeArray = ['and'] %}{% endif %} {# only set this array if exclude users exist #}
    {% set excludeArray = excludeArray |merge(['not ' ~ user.id]) %}
{% endfor %}

{# check if users should be excluded, I'm not sure what happens if you'd do .author(null) #}
{% if excludeUsers %}
    {% paginate craft.entries.section('bildupload').author(excludeUsers) %}
{% else %}
    {% paginate craft.entries.section('bildupload') %}
{% endif %}


How do I reset a user’s password or email them when I create an account? Is it possible to reset a users password from the Control Panel, I remember seeing an option for that before but not seeing it anymore?

Same goes for notifing users when you create their account, is there a way to trigger an email to them automatically?

If not maybe a plugin is in order?

If you are an administrator or your account has “administrate users” privileges, then there is a checkbox on the user’s edit page in the control panel that says “Require Password Reset on Next Login” which, if checked, will force the users to reset their password the next time they attempt to login.

When creating a new account, if you leave the “Require Email Verification” checkbox checked, the user will get an email asking them to confirm their email address and set a new password on their account when the click the link in the email.

Note that the password reset and account verification process requires email to be configured and working properly under Settings->Email in the control panel.


Find Related Entries with Identical Tags I'm trying to show related entries for a single item.

I want to look up a specific tag(s), and search for any entries that share the same tag(s) then display those related items.

I've read through the documentation and searched around but couldn't find a solution.

Marion's answer is fine but you can also do it a different way, and move the conditional logic out of the for loop. By adding it to the query, you can ask for a specific amount of items to grab, and it won't mess up the loop.index values if you need them.

This is how I would do it.

{% set relatedEntries = craft.entries.relatedTo(tag).id('not ' ~ currentEntry.id).limit(4).find() %}

{% if relatedEntries | length %}
    {% for e in relatedEntries %}
        {# entry stuff here #}
    {% endfor %}
{% endif %}


Element API - UrlHelper generates backwards slashes (regex) I am generating a url within Element API:

'profile' => UrlHelper::getUrl("directory/company/{$member->id}/{$urlslug}"),

which outputs:

http:\/\/craft.fira\/directory\/company\/1501\/abet-limited

What do I need to do to turn this into a real url without the backwards slashes "\"? As far as I understand this is a regular expression (regex) version of the url?

I will be using javascript to put this on the page, so it could either be fixed at source in the Element api php code, or alternatively when scraping through the JSON with Javascript.

Thanks in advance guys! :-)

The plugin probably uses PHP's json_encode to serialize the data and it automatically escapes quotation marks and backslashes to conform to the JSON format. Escaping the forward slashes of your URL wouldn't actually be necessary, but I just found this on StackOverflow which might give an idea why the function escapes them anyways:

https://stackoverflow.com/questions/1580647/json-why-are-forward-slashes-escaped

But you shouldn't really care about this behavior at all, because however you gonna consume that JSON string, the parser (e.g., jQuery.parseJSON()) should handle the unescaping for you.


How can I correctly set the time of a dateTime field from a front-end form? I am using jQuery-timepicker to give the user an option to pick a starting time and ending time.

My init looks like this:

$('.timepicker').timepicker({
    scrollDefault: 'now'
});

When I save the entry as attached (screen below) it is displaying the time + 6 minutes.

My template looks like this:

<input type="text" name="fields[myTimes][{{ block.id }}][fields][startDateTime][date]" class="form-control datepicker" value="{{ block.startDateTime|date('m/d/Y') }}">

<input type="text" name="fields[myTimes][{{ block.id }}][fields][startDateTime][time]" class="form-control timepicker" value="{{ block.startDateTime|date('h:m') }}">

<input type="text" name="fields[myTimes][{{ block.id }}][fields][endDateTime][time]" class="form-control timepicker" value="{{ block.endDateTime|date('h:m') }}">

When I save my form, everything looks like it is saving correctly, its always +6 min. I'm not sure what I am doing wrong.

Thank you for any suggestions!

EDIT

Here is another example. I have saved for 9:00PM - 10:00PM
It saves correctly, but the template shows +6 still. :)

Thank you everyone for your suggestions - I need to keep reading/digging more to fully understand, but it seems that it was just a formatting issue.

{{ block.startDateTime|date('H:i:s') }}

Renders the correct time on the template.


How to show a product from a field entry I'm trying to bring in recommended products for adding to a bigger purchase. I set up a simple matrix but can't seem to figure out how to pull product information. This is what I have so far, it throws no errors, but it also gives nothing.

{% for block in product.recommendProduct %}
    {% set i = i + 1 %}

           {% set image = block.chooseProduct.mainProductImage.first() %}

{{ block.chooseProduct.title }}

{% endfor %}

This should work:

{% set image = block.chooseProduct.first().mainProductImage.first() %}

Explanation:
your field handle in your product is called recommendProduct (matrix) that contains a relation chooseProduct. Your block.chooseProduct is an object of type ElementCriteriaModel so in order to fetch the product you need to call the first() method (or something similar). So if you have multiple products in your chooseProduct field your code would look like this

{% for block in product.recommendProduct %}
{% set i = i + 1 %}

       {% for relatedProduct in block.chooseProduct %}
            {% set image = relatedProduct.mainProductImage.first() %}

{{ relatedProduct.title }}

       {% endfor %}

{% endfor %}


I'm getting a 'couldnt save entry' error for a single but all required fields etc are filled I'm getting a couldnt save entry error, but all the fields are filled and there are no additional errors or input highlighting. Has anyone has this problem? Tried clearing the cache and checking the logs but nothing, I was able to fill it in fine before but no longer.

This is a screen shot of the error.

Any help would be appreciated.

Thanks!

Under your single's section settings, you had an invalid URI format for the cy_gb (Welsh) locale: ein heiddo.

URI's can't have spaces in them.  It'd be nice if Craft could warn you that the URI format is invalid (no spaces, all URL safe characters, etc), but it's difficult because Twig code is allowed in those fields and all sorts of characters that aren't URL safe are allowed in Twig markup.


Removing URL's from Existing Entries We've created a site which now has 40 entries in a Structure.  We need to retrospectively remove the URI's because there isn't an individual page for each entry, they're all on one page but search engines are tracking individual pages.

We've removed {slug} from the Section and replaced with 'projects' (no quotes) but of course CraftCMS sees this as duplicate when it tries to resave all the entries.

Any suggestions?

Many thanks

As a quick but not elegant fix, You can disabled the entries you don't want to show up in the url.

When you want to use the content just put

 craft.entries({
   section: someSection,
   status: null
 })

or

 craft.entries({....}).status(null)


Can you save a variable in session? Is there any way to save a variable in the Craft session inside a controller?

I'm running a cron job and I need to store a variable as a session for every run to see if a condition matches.

Craft's HttpSessionService is a thin wrapper for PHP's global $_SESSION variable.

You can use:

craft()->httpSession->add($key, $value)

and:

craft()->httpSession->get($key)

to save and retrieve values from it.


Searching Content Back-end Currently in the admin panel, all entries per channel appear in a single list. Is it at all possible (at least, by default) to filter/search by type?

For instance a dropdown of all entry types, or just 'type: article' in the search form.

I know it is quite easy to do from the front-end, would it require a plugin to add the functionality to the back-end?

Indeed: http://buildwithcraft.com/docs/searching

Anywhere there is a search bar in the control panel, you can use any of the syntaxes listed on that page.


Blank / white screen for admin/utils/ /admin/utils/serverinfo and /admin/utils/phpinfo are both showing empty pages. There aren't any errors appearing in any logs.

In case it's related, the same site won't allow .jpg images to be uploaded. The progress bar reaches 100% but then it remains stuck.

Running Craft Pro 2.5.2755.

UPDATE

Running devMode true revealed the following error:
Parse error: syntax error, unexpected '[' in /nfs/c10/h03/mnt/175833/domains/example.com/craft/app/controllers/UtilsController.php on line 292

That error is a bug in Craft that's been fixed for the next release.  That line is PHP 5.4 array syntax and your server is still using PHP 5.3 (Craft still supports back to PHP 5.3).

In the meantime, you can go to the line it's complaining about and change:

$serverArray = [];

to:

$serverArray = array();


Dynamic background image I'm super new to Craft and was wondering if someone could help.

I'm trying to set up a hero banner. So there will be a full-width image, on top of this will be the heading text and a CTA button.

I'd like the background to be editable by the user so have set up a field for this called 'hero image'. This is how it looks now but it doesn't seem to be working:

                            {{ entry.description }}

                        {{ entry.buttonText }}

I'm so confused!

Any help would be greatly appreciated!

I see a few issues with your code. (1) Unless you set heroImage as a variable somewhere, then you need to change heroImage to entry.heroImage. (2) But, an asset field returns an assetModel, not the actual image. To access the image, you need to use .first() to select the first asset in the assetModel. (3) Then you need to access the URL on that image, by using url.

This code should work:

{% set heroImage = entry.heroImage.first() %}

 {{ entry.description }}

                        {{ entry.buttonText }}


Check if local image differs from image on Craft I'm writing a plugin which synchronizes the content from an external database with the Craft database.

For the images I receive URL's to the external image then store them in the temp storage and upload them to Craft assets, which works fine.

I now want to check additionally if the image in the temp already exists in crafts assets and if the images are identical ( checking for file size ).

Ideally comparing the external image and the image in the assets even before saving the external one to the temp.

The file size from the external source is identical to the tmp saved file but after uploading the file to Craft it somehow gets a little bit bigger so checking for the file size doesn't work.

Am I doing something wrong ? Should I check for something else than filesize?

This might be related to this question

It is related to the linked question since any images uploaded through Craft's AssetsService go through a "cleansing" process to remove any potentially embedded malicious scripts so the file size will inevitably be +/- the original by a small percentage.

What you can do is instead of uploading through the AssetsService, programmatically copy the file to the final destination on the file system in an Asset Source, then trigger Asset indexing like how the ToolsController does for the AssetIndexTool.  That will bypass any cleansing operations.


Get the location and id of asset volumne Is it possible to get the location (/media) and id (1) of an asset volume from within a Craft template?

Of course it is. You can get the volume as you want, for example

{% set volume = craft.app.getVolumes().getVolumeByHandle('images') %}

Of if you have an asset

{% set asset = craft.assetFieldHandly.one() %}
{% set volume = asset.getVolume() %}

And output the information

{{ volume.path }}
{{ volume.id }}

if {{ volume.path }} contains an alias you can do {{ alias(volume.path) }} to display the resolved path


Plugin migration question Reposted from Slack

I have tried to create a migration using console (as per docs) but whilst it created a migrations folder it did not create a migration file. So resorted to creating manually but now getting the following error:

Status: Internal Server Error
Response:
Craft\Exception

Could not validate update handle.

The offending migration file can be viewed at https://gist.github.com/cole007/4bfff23c693ca496ca4929f464df2a05

Looking into the Update Controller that is throwing the error it seems to be down to the _getFixedHandle() method where $data['handle'] is returning empty but no idea why this is.

Any thoughts on debugging or resolving? Site launch is imminent so need to get to the bottom of why this is happening soon!

Thanks,

Cole

Okay - this was a problem at our end.
We had a plugin which provided a twig extension that modified Craft's own hash method which was causing issues with the migration update.

Consider solved!


Is there any way to create twig extension without a plugin? I want to create custom twig extension without any plugin dependency. Is anyone has solution for this?

Short answer:
No.
Longer answer:
Sorry, no... but there's a good reason for that.
Twig is a template language. PHP is business logic.
In proper application design, you separate the business logic from its presentation typically in some sort of MVC structure.
This sounds complicated, but it really makes your website/application a lot easier to maintain over time and keeps the different components from bumping into each other which can also improve security. (I'm looking at you WordPress where template code is often scattered over various plugins, themes, and much more.)
Plugins (and also modules upcoming in Craft 3) typically fall into the business logic category. Twig does a lot by itself but sometimes you need to write some PHP to do more—which I'm assuming you're trying to avoid.
Twig itself is obviously PHP so if you want to extend it, you need to write PHP.
What kind of Twig extension do you want to create?
The most common is a Twig filter, where a template sends Twig a value and then your code wrestles with the data and sends something back.
This is straightforward to do. If you use pluginfactory.io it will generate the necessary bootstrapping needed to get a Twig filter working.  Also check out Cameron's Spear's write up on the nitty gritty.
On the other end of the spectrum, creating your own tags (such as {% myTwigTag %}) and tests requires more work.
That should be more of a rare occurrence but it has been done (for example Marion Newlevant's Break/Continue extension).


How can I Prevent CSRF Tokens from being Cached? We have a Craft site in which we include a partial that includes in several different places. CSRF is enabled, and we're appending {{ getCsrfInput() }} to the form.

Because of the way we've set up the site, and are including this partial in so many places, nearly all of the forms we're rendering are using cached CSRF tokens, which invalidates them.

Is there a way to prevent Craft's {% cache %} tag from including the generated CSRF token without ending the cache and starting it up again each time? (eg, {% endcache %}{{ getCsrfInpt() }}{% cache %})

I worry doing so would be risky, because we may include this partial in a part of the site that is not cached, so there'd be no cache tag to end.

Thanks!

Update: I failed to mention that our site works right now without Javascript, so I'd like to avoid it. Otherwise, Lindsey's answer is perfect.

You can do something like this:

// First, set all your cached content to a variable:
{% set myContent %}
  {% cache %}
    {# YOUR CACHED CONTENT #}
    %%MY_CSRF%%
  {% endcache %}
{% endset %}

// Then, run a replace on your cached content to insert the new CSRF
{{ myContent|replace({'%%MY_CSRF%%': getCsrfInput()}) }}


Is it possible to output Profiling Summary Report (devMode) Is it possible to output Profiling Summary Report when in devMode? Looking to print this out onto a template:

Time:   0.36980s
Memory: 20,563Kb
Total Queries: 19

Off the top of my head, I don't think it's going to be possible, at least in the context of outputting it from a Twig variable.  That info comes from Yii's CProfileLogRoute class, which Craft extends at etc\logging\ProfileLogRoute.

But with all of Yii's logging, that stuff doesn't get flushed to disk (for FileLogRoute) or to the browser's console (for ProfileLogRoute) until the very end of the request, which will be after the template has already rendered.

If you view source with devMode enabled, you can see they just append it to the very end of the DOM.

Maybe you could write a plugin that used craft()->log->addLogRoute() that added your own custom ProfileLogRoute that extended Craft's and instead of appending to the end of the DOM, added it to some other part of the template, but seems like a pretty brittle solution.


How to add class to ul ol tag in redactor by using formattingAdd I try to add a class to tag ul by field Redactor. I have prepered special config file for Redactor. For example in Redactor field a have a created simple list so i select this list and next from formatting option i choose my new created option which should add a class to that ul tag and
unfortunately it not works.

However if i use this option on standard paragraph class is added. So i have not idea what i do wrong.

Below content my config file:

{
  "buttons": ["formatting", "bold", "italic", "unorderedlist", "orderedlist", "link", "html", "fontcolor", "image"],
  "plugins": ["fullscreen", "fontcolor", "alignment"],
  "linkNewTab": true,
  "toolbarFixed": true,
  "formattingAdd": {

    "list-columns-3-each-under": {
      "title": "list-columns-3-each-under",
      "api": "module.block.format",
      "args": {

        "type": "add",

        "class": "my-class-for-list"
      }
    }

  }

}

The unfortunate answer here is you can't add classes to ul or ol elements using formattingAdd, at least that's the way I interpret the documentation. See: https://imperavi.com/redactor/docs/settings/formatting/#s-formattingadd
It states:

formattingAdd can only be applied to block tags (p, pre, blockquote, div, heading, etc).

I suspect the etc there also encompasses ul and ol elements, even though they are block elements.
The best workaround I can come up with for this is to have a wrapper around the list and apply the class to that wrapper. As this would be fiddly in Redactor alone, I use a matrix field type to add blocks of content, with the option to add a class to the wrapper for that particular block.
This page describes this method of building out content https://nystudio107.com/blog/creating-a-content-builder-in-craft-cms


How to get user's photo url without transform? Craft 3: I'm trying to get User Photo URL WITHOUT any transforms, but none of those options seems to work:
(some of it prints the url with some transform)

user.photo
user.getPhoto()
user.getPhoto('original')
user.getPhotoUrl()
user.getPhotoUrl('original')
user.photoUrl()
user.photoUrl('original')

There is no DOCs for this yet on the craft 3 site.
Anyone know?
Thanks

According to the Craft 3 source code, User::getPhotoUrl() has been deprecated. Use getPhoto() to access the photo asset (if there is one), and call its getUrl() method to access the photo URL. (Also mentioned in the changelog.)

So assuming you've set user to something already in your template, the correct way to get the photo in Craft 3 is:

{{ user.photo.url() }}


Initiate Multiple Google Maps Instances I am trying to initiate multiple Google Map instances on a page.

I need to set a dynamic ID for each one. I've tried doing it with loop.index but no joy.

{% for marker in event.eventMap.getMarkers() %}
    <div class="google-maps">
        {% set options = {
            id: 'map',
            width: '100%',
            height: '150px',
            options: {
                disableDoubleClickZoom: true,
                maxZoom: 15,
                minZoom: 5,
                scrollwheel: false
            }
        } %}

        {{ craft.googleMaps.map() }}

        {{ craft.googleMaps.data('map', event.eventMap) }}

    </div>
{% endfor %}

Something like this?

{% for marker in event.eventMap.getMarkers() %}
    {% set mapId = 'map' ~ loop.index %}
    <div class="google-maps">
        {% set options = {
            id: mapId,
            width: '100%',
            height: '150px',
            options: {
                disableDoubleClickZoom: true,
                maxZoom: 15,
                minZoom: 5,
                scrollwheel: false
            }
        } %}

        {{ craft.googleMaps.map() }}

        {{ craft.googleMaps.data(mapId, event.eventMap) }}

    </div>
{% endfor %}


Commerce - How do I add the purchaser of a specific product to a user group? I want all buyers of a specific product to automatically be added to a specific user group.

How do I do this?

Create a business logic plugin if you haven't already.

Two good ways of doing that are : Business Logic Plugin or via http://pluginfactory.io

Then, in your plugin's main file in the init method, register a listener method:

public function init()
{
    craft()->on('commerce_variants.onOrderVariant',
        [
            craft()->businessLogic_logic,
            "onOrderVariantHandler"
        ]
    );
}

Then, implement the method (I do this in my class BusinessLogic_Logic Service):

public function onOrderVariantHandler($event){

    $variant = $event->params['variant'];
    if ($variant->product->id == "4194" ){
        $user = craft()->userSession->getUser();
        craft()->userGroups->assignUserToGroups($user->id, [3]);
    }

}

Obviously make sure you use the right ids for your particular products & groups!

Note you can also just implement the method directly in init() if you want to keep things very simple - but the above method makes for a cleaner main plugin file and once you start doing a lot of this sort of thing (which is where a lot of the real power of Commerce lies I think) - separating the logic into a service and just registering the handlers is a more ordered way to go I think.

craft()->on('commerce_variants.onOrderVariant', function($event){
    $variant = $event->params['variant'];
    if ($variant->product->id == "4194" ){
        $user = craft()->userSession->getUser();
        craft()->userGroups->assignUserToGroups($user->id, [3]);
    }
});


Craft CMS max image resolution? Is there a max image file resolution set up in Craft CMS that can be uploaded?

I'm trying to upload a series of .jpg images in a Matrix to create a gallery, and I've noticed I'm not able to upload any file that is over somewhere around 4000px in width.

At first I believed it was something to do with the PHP file upload limit, but I'm able to upload .jpg files that were over 5mb with a 2880px width.

Craft does have the maxUploadFileSize config setting (defaults to 16MB).  If what you're trying to upload is under that size, you're probably running into environmental limitations.  I'd check your php.ini file's post_max_size, memory_limit and max_execution_time settings as a starting point.


Does Craft CMS have an API? Does Craft CMS have an API that third-party webapps can access?

Maybe a REST API which you can log in to and send GET, PUT, POST, DELETE commands to, from a third-party app?

It seems like it should have an API, by the statement of the creator:

  A key part of the architecture is our service layer. All of the
  business logic in Craft happens in service classes, which provide APIs
  that anything else in the system (including other services) can talk
  to.
   - http://www.thenerdary.net/post/48123188844/interview-with-brandon-kelly-creator-of-craft

But then again, some other people who have tried integrating towards Craft CMS says it doesn't:

  I ran into some trouble with the API. Shit, Craft doesn’t freakin’
  have one! I assumed it would, oops.. So I researched how to do it. I
  knew I could probably fake it and output json using template tags but
  no-one wants to do that. I looked at some API controllers but non of
  them worked very well. In the end I found a nice plugin called JSON
  Expand that converts entries from Twig into JSON. -
  http://abandon.ie/notebook/using-angularjs-with-craft-cms

I'm confused. If it has an API, what kind is it, and what protocol does it use? REST? SOAP? RPC? Something else?

And where is it documented? A simple 'hello world' or 'transmit som data into Craft CMS' example would be really helpful.

No, Craft doesn't have a REST API (edit: or any other web service) built-in. The "API" mentioned in the first quote (and elsewhere related) would be the more generic meaning of the term and refers to the service layer.

With a very consistent MVC based architecture based on Yii, Craft is well suited for REST implementation, though. See this G+ thread for P&T weighing in on the subject.

As a native REST API isn't part of the core, one would have to added to Craft via a plugin.

There's at least one plugin out there, though I haven't tried it (or any others) myself.

Edit

It should be mentioned that after I wrote the above answer, Pixel and Tonic has released the Element API plugin - making it easy to build a REST API with Craft. Element API is pretty basic (only GET requests), but can probably be extended with a custom plugin to support additional HTTP methods.

P&T has also stated that they want Craft 3 to have a full, built-in REST API at some point.


Loop through category groups I've looped through individual category groups to find each parent/child category, but is there a way to loop through and only show Category Group names?

I'm not seeing any obvious ways to access groups directly in Twig. There may be a more direct way, idk — but this should work.

{% set categoryGroupNames = [] %}
{% for category in craft.categories %}
    {% set groupName = category.getGroup.name %}
    {% if groupName not in categoryGroupNames %}
        {% set categoryGroupNames = categoryGroupNames|merge([groupName]) %}
    {% endif %}
{% endfor %}

{% for groupName in categoryGroupNames %}
    {{ groupName }}
{% endfor %}


{% block content %} is a no-go in template/subfolders I’m on a mac running MAMP and my install is functional. Localhost will direct to and display files in “templates” but it wont fully cooperate with subfolders within templates, such as templates/news. From templates/news/_entry.html, I’m able to {% extends "_layout" %} to the _layout.html, but I can’t call up anything via the block. Using {% block content %} is a no go.

I’m sure it’s a simple fix, but it’s hard to search for an answer when I don’t know where to start. Can anyone help?

Attached is a screengrab of my templates folder. You might notice from the "brews" folder that I've been following the Mijingo tutorial for Craft CMS. Nonetheless, the default "news" folder also doesn't load the block.

In this case, it was just human error and ignorance of how hidden template files work through the CMS.

I believed that I should be able to call the hidden file in the browser, via something like "base_url/subfolder/_hiddenfile.html" and partially I was able. For whatever reason, using this primitive test method, I was able to see the header and footer, but not the block content, in the browser window.

The fact is, what I was doing was not a viable test. I don't understand why, but that doesn't matter.


How to check if currentUser matches a users field within an entry? I've already found the entry, and the 'users' field can contain multiple users.

I asked this on the Slack chat and Brad Bell kindly came to the rescue.

{% set match = false %}

{% for user in entry.users %}
    {% if user.username == currentUser.username %}
        {% set match = true %}
    {% endif %}
{% endfor %}

{% if match %}
    User matches!
{% endif %}


Twig template outputting blank page on non-"dev" environment I've created a base twig template which contains some basic "maintenance mode" logic. This works perfectly as long as the main ENVIRONMENT in the .env file is set as dev, but fails for staging or production.
{% if site.maintenanceMode is defined and site.maintenanceMode %}
    {% if site.maintenanceIpAddress is defined %}
        {% set currentIpAddress = craft.app.request.userIP %}
        {% if currentIpAddress != site.maintenanceIpAddress %}
            {% include('/maintenance') %}
            {% exit %}
        {% endif %}
    {% else %}
        {% include('/maintenance') %}
        {% exit %}
    {% endif %}
{% endif %}
<!DOCTYPE html>
<html lang="en"…

Being fairly new to CraftCMS, I'm somewhat at a loss as to why this might be occurring and there's nothing in either the …/storage/logs/web.log file or the main nginx error log file. (In short no errors appear to be being thrown.)
I've tried flushing all of the available caches (including the template cache, etc.) and rebuilding the config, etc. to no avail.

It looks like you're reinventing the wheel here: in Settings → General, you can toggle the site live/offline. When the site is offline, Craft serve the templates/503.twig templates, no matter which URL you hit.
You can even configure users to have access to the site, when it's offline. To do so, go to the user edit page in the control panel and then to the Preferences tab.

Regarding your specific blank page issue, it's caused by a mixup between the Twig include function & the Twig include tag.
Function
As per the documentation:

The include function returns the rendered content of a template.

You then have to do something with the returned value or it is pointless.
Tag
The documentation of this tag is misleading. It states that :

The include statement includes a template and returns the rendered content of that file

but what it really does is output the rendered content of that file.
In your case, you use the function but forget to output its value. To fix you're issue, you can either use output delimiters ({{ include('/maintenance') }}) or use the tag instead of the function ({% include'/maintenance' %}).
The documentation of the include tag encourages us to prefer the former:
As of Twig 1.12, it is recommended to use the include function instead as it provides the same features with a bit more flexibility
Solution
TL;DR
Use {{ include('/maintenance') }}.


Audio file won't play using resourceUrl inside plugin Essentially I'm moving a static HTML site into Craft. I've created a new plugin for the site and have gotten a good chunk of it working however I'm having an issue where audio files won't play.

The site is supposed to have music auto-playing and looping (it's a site for kids before you start judging me), and it works correctly on the static site, however nothing plays in my Craft instance and when I go to the direct URL for the audio file it won't play in browser either but doesn't give me a 404. If I "Save As" it does then download correctly.

Code is very simple:

<audio autoplay loop>
        <source src="{{ resourceUrl('somesite/audio/some_theme_full.ogg') }}" type="audio/ogg">
        <source src="{{ resourceUrl('somesite/audio/some_theme_full.mp3') }}" type="audio/mpeg">
</audio>

The src generates correctly as e.g http://site.local/cpresources/somesite/audio/some_theme_full.mp3?d=1513706441.

Any help would be wonderful!

I think the cleanest way to solve your issue is to create a new Asset for each of your audio files and relate it to your entries.

<audio autoplay loop>
    {% set audioFiles = entry.assetFieldHandle.all() %}
    {% for asset in audioFiles %}
        <source src="{{ asset.getUrl() }}" type="{{ asset.getMimeType() }}">
    {% endif %}
</audio>


Getting average of number field values I'm getting close to finishing my first project on Craft CMS but I have one problem.
I'm using number fields to rate items in my entries. It looks like this:

I will have around 6-7 fields and I need to get the average rating of them to display in the front end.
{% set ratingAverage = entry.dizainas + entry.ekranas + entry.veikimas %}

{% set ratingsSum = ratingAverage / 3 %}

<strong>{{ratingsSum|number(decimals=1)}}</strong>

In fact, some of those fields might be left empty as well so it's needed to skip them.
Can someone help me out with this?

Something like this should work:
{# Setup an arry of the field handles you're interested in #}
{% set fields = ['num1', 'num2', 'num3'] %}

{# set some defaults #}
{% set totalAmount = 0 %}
{% set totalFields = 0 %}

{# loop through the field array #}
{% for field in fields %}

    {# grab the field's value from the entry #}
    {% set value = attribute(entry, field) %}

    {# skip over fields that were left blank, but count fields where 0 was entered #}
    {% if value is not empty and value >= 0 %}

        {# add to the running total and running number of fields with values #}
        {% set totalAmount = totalAmount + value %}
        {% set totalFields = totalFields + 1 %}

    {% endif %}
{% endfor %}

{# do some math #}
{% if totalFields > 0 %}
    {{ (totalAmount / totalFields)|number(decimals=1) }}
{% endif %}


How to render template instead of throwing an error? I'm working on a plugin that hooks into Craft's Guest Entries plugin.

I want to send a confirmation mail after an entry has been saved. This works nicely so far.

Now I want to catch any errors in the mail service. This works nicely so far. Here's my code:

private function mailHandler($from, $to, $subject, $text)
{
    try
    {
        $message = new \craft\mail\Message;

        $message->setFrom($from);
        $message->setTo($to);
        $message->setSubject($subject);
        $message->setTextBody($text);

        Craft::$app->mailer->send($message);
    }
    catch (\Exception $e)
    {
        echo \Craft::$app->view->renderTemplate('error', ['error' => 'Test']);
        die();
    }
}

There are two problems I'm facing:

1) I have to "stop" the controller action, that's why I need the die. This seems dirty though, is there any other way I could stop the controller?

2) If I do it like this, my error template is rendered, but without any CSS. What am I missing there?

Thanks a ton for your help!

You can see common patterns for this in Craft's own controllers.

For example in https://github.com/craftcms/cms/blob/master/src/controllers/EntriesController.php#L499-L507, if there's a problem, you can catch the error, set it on a route variable and return null so the original template can display it.

Craft::$app->getSession()->setError(Craft::t('app', 'Couldn’t duplicate entry.'));

// Send the original entry back to the template, with any validation errors on the clone
$entry->addErrors($clone->getErrors());
Craft::$app->getUrlManager()->setRouteParams([
    'entry' => $entry
]);

return null;

If you don't want to let the original template handle the error, then you should be able to do something like this from your controller:

return $this->renderTemplate('error', ['error' => 'Test']);


Speeding up the pageload of a page with a huge Matrix We've got a site with a navigation on top, which navigates to anchorpoints on the page, but the whole page is built with 1 matrix. The page will probably be very long and will have all kinds of images (small & big) in it. I've set image transforms, so images won't be a problem.
BUT: is it possible to speed up the site with lazyloading or something like that when there's 100+ matrix elements in it?
And on that note I guess the biggest problem we'll face is having the anchor points still working: if they click the anchorpoint they should be able to scroll to that point, even if it's not visible yet.

Is this possible?

Kind of a broad topic, but here are some resources to get your started:

Great article on Craft optimizations here: http://www.patpohler.com/performance-optimization-craft-cms/
Make sure your environment isn't a bottleneck.

You're not on an overloaded shared hosting server.
PHP has plenty of memory allocated to it.
Your server has plenty of resources (memory, CPU, disk space).
Run PHP 7.

Eager load elements as necessary: https://craftcms.com/docs/templating/eager-loading-elements
Judiciously use template caching in Craft where necessary: https://craftcms.com/docs/templating/cache
Enable devMode and review the profile output in the browser's console (as well as craft/storage/runtime/logs files to spot any bottlenecks (# of queries, types of queries, plugins involved, etc.)
Use template hooks as necessary.
Go through the plethora of client side things that can slow a page down. Google Pagespeed Insights is a good place to start for that.
If none of these work, you can looking into changing your content architecture so that 100+ Matrix blocks on one page aren't necessary.


Selecting all parent users and their related children Ok, I need a MySQL pro.

The setting:

Hundreds of users
User can be a child of other users, through relation field 'myParents'
I need a list of users, and their child(ren), related to an entry (through relation field belongsToGroups)

I don't want to use $criteria->find(), because it returns objects, which makes it terribly slow. So, I want to create a db query. What I have now, is this:

$parentsWithChildren = craft()->db->createCommand()
        ->select('u.id userId, u.firstName parentFirstName, u.lastName parentLastName, c.firstName childFirstName, c.lastName childLastName')
        ->from('users u')
        ->join('relations r', 'u.id = r.sourceId')
        ->join('relations uc', 'u.id = uc.targetId')
        ->join('usergroups_users g', 'u.id = g.userId')
        ->join('users c', 'uc.sourceId = c.id')
        ->where('r.targetId = '.$elementId)
        ->andWhere('uc.fieldId = 92')
        ->andWhere('g.groupId != 5')
        ->order('u.id')
        ->queryAll();

This return a nice list of all users, children included, but only if a user has children. In short: I also need the users without children. Any SQL guru willing to help me out, it's been a long day ;)

One option would be to use leftJoin() instead of join(), which will still return the record if the joining table row doesn't exist. The values will be joined as NULL.

  The LEFT JOIN keyword returns all rows from the left table (table1), with the matching rows in the right table (table2). The result is NULL in the right side when there is no match.

http://www.w3schools.com/sql/sql_join_left.asp

If you needed more control, you could always incorporate some aggregate functions in SQL to do a count an the records found, and you could perform additional conditional statements with the HAVING, instead of WHERE (which won't work) since aggregate data isn't stored in the db.


Is it possible to call a variable within a tag pair? Having already defined foo, I tried this:

{% for block in availability.{{ foo }} %}

This gives error:

Expected name or number

Can anyone please tell me the right way to go about this.

Try this:

{% for block in availability[foo] %}

The square brackets let you access a variable variable name on an object.

As a general rule you never put {{ }} inside of {% %} tags in twig.


How to trigger updateElements when hide modal? Is it possible to refresh an element's list when closing a modal? I have a modal ready with:

onHide : function(){
    //but all what I tried doesn't work here

    //1: This will do the trick, but there is some bug with "Double-instantiating a select on an element" then the check box for the actions appear multiple times.
    Craft.elementIndex = Craft.createElementIndex('Plugin_ElementType', $('#main'), {
        context:        'index',
        storageKey:     'elementindex.Plugin_ElemenetType'
    });

    //2 I was searching for some global function as updateElements
    something like this: Craft.cp.updateElements()
    or: Craft.Plugin_ElementType.updateElements(); but no success

}

I need this because in that modal I change, delete data from my elements so I have to update the list, if is possible without to reload the page of course. Thank you in advance!

If the page is rendered from a template that extends _layouts/elementindex, then the Element Index class instance is available at Craft.elementIndex. So all you’d need to do is include this in the settings object when creating your Modal instance:

onHide: function() {
    Craft.elementIndex.updateElements();
}


How do you downgrade Craft I'm trying to test a new plugin in development, is there any easy way to downgrade the version of craft?

See here for how you can download previous versions of Craft.

All you need to do is replace the existing app folder with the one you just downloaded and restore a database backup that has the same build/version numbers in its craft_info table.


Channel content in structure I'm posting a lot of newbie questions today, hope that's ok. It will get better!

I would like to add a channel (list/detail) to a structure page.

Home > Pages > List Page

I'm sure I'm looking at it the wrong way. I'm used to create this list page as a "real" page in a structure in another CMS (TYPO3) and add the "channel" content as a plugin.

Maybe in Craft, you don't do that (create the channels "containing page") at all? But then again, how do you tell the main site navigation it should link to the channel?

I finally found out craft allows multiple entry types. So a regular "structure" page can be of type "page" or, eg, of type "listpage".

I created the second entry type and gave it a field function instead of the content.

In my regular structure page, I did the following:

{# switch between content pages and list pages; if list page, display selected list #}

{% if entry.type == 'listpage' %}

{{entry.title}}

            {% switch entry.function %}
            {% case "interviews" %}
                {% include "interviews/_list.html" %}
            {% case "researchprojects" %}
                {% include "researchprojects/_list.html" %}
            {% case "seminars" %}
                {% include "seminars/_list.html" %}
            {% endswitch %}

{% else %}

{{entry.title}}

            {{entry.richtext}}

{% endif %}

Great!


Order by related field title I have a series of talks that have speakers as a related entry.

I'm looking for a way to order the talks by the last name of the speaker (the last name is the title of the speaker channel).

You probably have to loop through all the speaker (ordered by lastName) that are related to the talks (the speaker entry is the targetElement). Then use one craft.entries (ElementCriteriaModel) for each loop to get the talk entry.

See this Q/A for a comparable problem.


How do I send PayPal the Craft Commerce Order Number? The client is using PayPal Express for the payment gateway. When orders are placed, Paypal shows the ID for the order, not the Order Number. Is there somewhere I can change that?

Commerce V1 - You can use a hooks for this:

https://craftcommerce.com/docs/hooks-reference#commerce_modifygatewayrequestdata

or

https://craftcommerce.com/docs/hooks-reference#commerce_modifypaymentrequest

...basically, start by dumping all the data to look at what is being sent, then modify it as you need.  Here's an example of something similar (I truncate the data to make sure it fits the gateway's limits):

    public function commerce_modifyGatewayRequestData($data,$type,$transaction){

        # Dump the data to see what is there....
        BusinessLogicPlugin::log("commerce_modifyGatewayRequestData");
        BusinessLogicPlugin::log("data");
        BusinessLogicPlugin::log($data);
        BusinessLogicPlugin::log("type");
        BusinessLogicPlugin::log($type);
        BusinessLogicPlugin::log("transaction");
        BusinessLogicPlugin::log($transaction);

        # TRUNCATE any over-sized data eWay might not like....
        # Data limits come from here: https://eway.io/api-v3/#direct-connection

       if(isset($data['Customer']['FirstName']))
        $data['Customer']['FirstName'] = substr($data['Customer']['FirstName'], 0, 49);

       ... etc

      return $data;
   }


One structure section for multiple menu's (navigations) I want to use one structure section for multiple menu's (navigations). So I want all pages under topmenu in the topmenu (header) and I want all pages in the bottommenu in a menu in the footer. How can I accomplish this most easily in my twig file?

This is something i've used, it should work for you, the only downside to it is there being a hardcoded id.

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

{% set headerItems = nav.descendantOf(TopMenuId) %}

{% set footerItems = nav.descendantOf(BottomMenuId) %}

So you would just replace TopMenuId with the entry id of Topmenu and BottomMenuId with the entry id of Bottommenu

Then you will be able to loop through each nav :)

Edit

<nav>
 {% nav entry in craft.entries.section('contentPages').descendantOf(13) %}
    <li> <a href="{{ entry.url }}">{{ entry.title }} </a>
        {% ifchildren %}
            <ul> {% children %} </ul>
        {% endifchildren %}
    </li>
 {% endnav %}
</nav>


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

The images I use are for Craft Commerce.

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

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

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

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

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

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

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

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

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

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

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


Return to specific locale based on cookie? If we are storing a cookie of a locale the user choose, is there a way to detect that cookie in htaccess so the next time they visit the base url of the site it will take them to the same locale?

Storing the cookie

I'd recommend using the LJ Cookies plugin...

{% do craft.lj_cookies.set('locale', craft.locale, '', '/' ) %}

Retrieving the cookie

The LJ Cookies plugin is also capable of reading cookies, so you could simply put a conditional redirect at the top of your layout...

{% set currentLocale = craft.locale %}
{% set goToLocale = craft.lj_cookies.get('locale') %}

{% if goToLocale and (currentLocale != goToLocale %}
    {% redirect '/' ~ goToLocale %}
{% endif %}

If you insist on performing the locale redirect at the .htaccess level, that's also possible. It would provide you a small performance improvement, but may not be worth bypassing the simplicity of using LJ Cookies in your template.

Using .htaccess to perform a redirect based on a cookie value is beyond my expertise, and somewhat beyond the scope of the Craft SE site. But I did some quick Googling around for "cookie" and "htaccess", and found a few helpful links:

https://stackoverflow.com/questions/3978726/how-to-do-htaccess-redirect-based-on-cookie-value
http://www.askapache.com/htaccess/htaccess-fresh.html#Get_Cookie_Value


Fetch values for a single field across all entries in a section I have a section "Hotel Room" with a field "Sleeps" (number). There is no limit on the values that can be entered. On the frontend I want a list of all existing entered values for this field. So if I have these four entries:

sleeps=2
sleeps=2
sleeps=8
sleeps=10

I want an array [2, 2, 8, 10] to iterate over. Bonus points for unique/distinct values, but I'm well aware I can add a Twig filter to array_unique() it.

Is this possible using Craft's craft.entries lookups within Twig?

Getting that array is simple. Prepare an empty array, then loop through your entries and merge the "Sleeps" fields value to it.

To get your array with the unique values, you basically do the same but also save the value as the key on each iteration. If a key already exists in the array the key/value pair gets overwritten (→ good for you)!

There's a strange behaviour that setting custom numeric keys doesn't work with Twig, that's why I composed a string out of the value.

{# Prepare variables #}
{% set myArray1 = [] %}
{% set myArray2 = [] %}

{# Loop through entries of the "Hotel Room" section #}
{% for entry in craft.entries.section('hotelRoom') %}

    {% set value = entry.sleeps %}

    {% set myArray1 = myArray1|merge([value]) %}
    {% set myArray2 = myArray2|merge({ ('key' ~ value): value }) %}

{% endfor %}


Impossible to invoke a method ("limit") on an array... but it's not an array? I am receiving the error message "Impossible to invoke a method ("limit") on an array," but I don't think I am working with an array! Here is why I think that...

First I set an albums variable:

{% set albums = craft.entries.section('townAlbums').with(['townPhotoAlbum']).relatedTo(entry) %}

Then I loop through that object. I'm not calling .all(), so this is still an object, right?

{% for album in albums %}

Finally within this loop I am grabbing one image from the assets field townPhotoAlbum to use as a thumbnail or cover image for this album:

{% set albumCover = album.townPhotoAlbum.limit(1) %}

Why is it complaining about using .limit() on an array when it appears as though I'm still working with an object? Or am I overlooking something woefully obvious?

Thanks!

I'm not calling .all(), so this is still an object, right?

Nope.  When you execute the for loop, it will explicitly run the database query and return the array of results.  You're probably getting a deprecation error logged using that syntax as well since Craft wants you to use {% for album in albums.all() %}

See here in the docs:  https://docs.craftcms.com/v3/changes-in-craft-3.html#treating-queries-as-arrays

If you want the first results for the album cover, you can use:

{% set albumCover = album.townPhotoAlbum[0] %}