Not All Entries showing in feed page but do show in Page Source XML

I accidentally had loop inside of the description tag which strangely caused only 17 entries to post to the RSS feed. Below is an example of what was causing the issue:

<description><![CDATA[
  {% set speaker = craft.categories.group('speaker').relatedTo(entry).find() %}
  {% for name in speaker %}
  A Sermon from {{ entry.sermondate | date("l, F j, Y") }}: {{ entry.title }} by {{ name.title }}]]></description>
        <category>Podcasts</category>
        <category>Christianity</category>
        <author>{{ name.title }}</author>
        <itunes:explicit>No</itunes:explicit>
        <itunes:author>{{ name.title }}</itunes:author>{% endfor %}

After I set it outside the Description tag if gave me all my entries on the RSS feed. Here is my final feed code:

    <?xml version="1.0" encoding="utf-8"?>
    <rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
    <channel>
    <title>Sermons at Example Church</title>
    <atom:link href="{{ url() }}" rel="self" type="application/rss+xml" />
    <link>http://www.examplechurch.org/sermons/</link>
    <description>Weekly morning sermons from Example Church in Sab Diego, CA. For all of our sermon archives, please visit http://www.example.org/sermons.</description>
    <lastBuildDate>Sun, 17 Sep 2017 00:00:00 -0600</lastBuildDate>
    <language>en-us</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <itunes:author>Example Church</itunes:author>
    <itunes:summary>Weekly morning sermons from Example Church in Sab Diego, CA. For all of our sermon archives, please visit http://www.example.org/sermons.</itunes:summary>
    <itunes:owner>
      <itunes:name>Example Church - San Diego, California</itunes:name>
      <itunes:email>web@examplechurch.org</itunes:email>
    </itunes:owner>
    <itunes:explicit>No</itunes:explicit>
    <itunes:category text="Religion &amp; Spirituality">
    <itunes:category text="Christianity"></itunes:category>
    </itunes:category>
    <itunes:category text="Health"></itunes:category>
    <itunes:category text="Society &amp; Culture"></itunes:category>
     {% if podcastImage.podcastimage|length %}
    <itunes:image href="{{ podcastImage.podcastimage.first.getUrl() }}"></itunes:image>
     {% endif %}
    {% set entries = craft.entries.section('sermonEntry').limit(null).find() %}
     {% for entry in entries %}
    <item>
      <title>{{ entry.title }}</title>
      <link>{{ entry.url }}</link>
      <pubDate>{{ entry.postDate.rss }}</pubDate>
       {% set audio = entry.audio.first() %}
       {% if audio %}
      <enclosure url="{{ audio.url }}" type="audio/mp3"></enclosure>
       {% endif %}
      <guid>{{ entry.url }}</guid>
       {% set speaker = craft.categories.group('speaker').relatedTo(entry).find() %}
      {% for name in speaker %}
      <description><![CDATA[A Sermon from {{ entry.sermondate | date("l, F j, Y") }}: {{ entry.title }} by {{ name.title }}]]></description>
      <category>Podcasts</category>
      <category>Christianity</category>
      <author>{{ name.title }}</author>
      <itunes:explicit>No</itunes:explicit>
      <itunes:author>{{ name.title }}</itunes:author>{% endfor %}
      <itunes:keywords>Example Church,Sermons,Christianity,Jesus Christ,Bible Teaching,Discipleship,Service</itunes:keywords>
     </item>
     {% endfor %}
   </channel>
   </rss>


Sure is!  You'll want to bookmark this ridiculously handy page, but if you look under "Relations" you'll see the syntax you're looking for:

<select multiple name="fields[fieldHandle][]">
    <option value="13">Username One</option>
    <option value="42">Username Two</option>
    <option value="144">Username Three</option>
</select>


how to uninstall a plugin when there is no cp option

It isn't possible to uninstall a disabled plugin; you'll need to first enable the plugin, and then the Uninstall option will be available.

The correct way to remove a plugin is actually to first Uninstall it. After uninstalling, you can either run composer remove vendor/plugin-handle from the command line, or select the "Remove" option from the Control Panel (the "Remove" option is available for any plugin that isn't currently installed).

If you do it the other way around – i.e. remove the files before uninstalling the plugin – you're probably going to see some issues.


Is it possible to disable token expiration? Or prevent follow from bots?

I ended up adding a lightswitch for do not index. I am checking if this value exists in _layout.html if it does I am adding

{% if entry.noIndex %}<meta name="robots" content="noindex,nofollow">{% endif %}

I also updated my search results, sitemap entry template to check for the same thing and not include it in the sitemap file or the search results. As well as the dynamic sitemap.xml file. I believe this should be good.

Also I extended the token expiration but I think with the above approach, we will just publish like normal and remove the token expiration.


Default settings for HTML purifier and how to extend it

Craft won't merge your HTML Purifier config settings with the default ones, but the default ones are pretty simple, so I'd just include them with yours.

{
    "AutoFormat.RemoveEmpty.RemoveNbsp": true,
    "Attr.AllowedFrameTargets": ["_blank"],
    "HTML.AllowedComments": ["pagebreak"]
}


Image Upload & Editing Suddenly not Working

I was able to fix the issue. For some reason Media Temple had switched the PHP implementation from FPM served by NGINX to FPM served by Apache. Switching back to NGINX (or Fast CGI) fixed the issue. I know this issue has come up for others, so a true fix would be great for future reference....


I had some helpful advice via Craft's support channels. Here was the solution I arrived at with their assistance:

You can hard code the locale in index.php in the doc root.

define('CRAFT_LOCALE', $locale);

The normal approach seems to be that multiple index.php pages can be used in a multi-locale site. I prefered to keep the one, so I used this tiny hack that derives from the url what the desired locale is:

<?php

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

$url_folder = substr(substr($_SERVER["REQUEST_URI"],1), 0,
    strpos(substr($_SERVER["REQUEST_URI"],1), "/"));
$locale = 'en_nz';

if($url_folder === 'worldwide') {
    $locale = 'en_zz';
}
else {
    $locale = 'en_' . $url_folder;
}

define('CRAFT_LOCALE', $locale);

This hack is confined to the index.php so it seems pretty clean.


Looks like it was an issue with character encoding. I copied the {% cache unless craft.config.devMode %} from What are the best practices for using the {% cache %} tag?.

When I manually retyped out the conditional it worked properly.


"Craft CMS does not support backtracking to this version. Please upload Craft CMS 0 or later."

Turns out I hadn't fully uploaded the app folder when I tried to access it earlier. Tried again, made sure it was finished before renaming and it worked fine.


Sprout Import Doesn't Recognize Asset folderPath Property

folderPath is not supported when relating an asset to an Entry but there is a workaround. In your generation script you can call the code below to get the folderId with the given path:

$folderId = \craft\records\VolumeFolder::find()
->where(['path' => 'documents/pdfs/'])
->scalar();


Project Config On or Off for Production Server

Even if useProjectConfig was set to false, it's not a good idea to update Craft on a live site because, as you've discovered, errors sometimes happen.

There's even an allowUpdates config setting that we recommend people setting to false on the live site just so someone doesn't accidentally update Craft from the control panel.

The safer workflow is to have a dev/staging/test environment where you can perform the update first, verify that everything still works fine and then you can deploy the update files to the live site with a much smaller chance of something going wrong.

If you've decided to use Project Config, which it seems you have, then you should really not be doing updates on the live site from the control panel.

And you should also have allowAdminChanges set to false so no one can even make Craft settings changes from the control panel.

At that point, Project Config should be enabled in all of your environments and your config/project.yaml and composer.json and composer.lock files should be deployed to your live site along with a deployment process that runs composer install on the live site post-deployment.


A hash key must be followed by a colon (:) syntax error

You're nearly there! The and query you’re building just needs to be declared as an array:

{% set puppyAnimals = craft.entries({
    section: 'animals',
    orderBy: 'postDate',
    animalDateOfBirth: ['and',  "<= #{now | atom}", ">= #{now | date_modify('-1 year') | atom}"]
}).all()  %}

The brackets around the value provided for animalDateOfBirth was being interpreted as a single string, followed by a missing key.

(I also opted for Twig’s interpolation syntax to make the series of array elements a little clearer, and used the atom filter to produce fully-qualified dates)

  One more note: I switched the greater-than and less-than operators, as I suspect the query would have returned no results—(after today, but earlier than last year)!


How can I disable relative dates in elements index?

Until this feature get implemented, I think I'll go with the following workaround that I'm using right now.
It's based on  getEntryTableAttributeHtml hook where I reformat the date value to match the user locale preferences.

public function getEntryTableAttributeHtml(EntryModel $entry, $attribute)
{
    if ($attribute == 'postDate')
    {
        $localeData = craft()->i18n->getLocaleData(craft()->language);
        $dateFormatter = $localeData->getDateFormatter();
        $format = $dateFormatter->getDatepickerPhpFormat();
        return ($entry->postDate ? $entry->postDate->format($format) : '');
    }
}

or simply

public function getEntryTableAttributeHtml(EntryModel $entry, $attribute)
{
    if ($attribute == 'postDate')
    {
        return $entry->postDate;
    }
}

which will return the date in Y-m-d format regardless of locale.


Best way to handle redesign of large site

Set up a local development environment, and invest in a workflow as described here: Database & Asset Syncing Between Environments in Craft CMS


Just like you would add a regular favicon just in your head.
If you want it to be an uploaded picture I would say:

Make a global and add a field like "favicon" to it and upload your image there and display it like:

{% for image in favicon.fav %}
<link rel="icon" type="image/png" sizes="16x16" href="{{ image.url }}">
{% endfor %}

But what I always do is just go to a favicon generator like:
http://www.favicon-generator.org/

And upload your logo and copy paste that code in your <head> tags in your _layout.html file


Craft Commerce 2 - extend Order details page

To include additional tabs you can include several different field layout tabs in your field layout designer. When you open /admin/commerce/settings/ordersettings you can see the field layout for your orders. There you can click on + New Tab and drag and drop the fields you like


Check if an order has been refunded in a template?

You get the related transactions for an order with

order.transactions

So you can loop over the transactions like so:

{% for transaction in order.transactions %}
  {{ transaction.type|title }}
  {{ transaction.status|title }}
  {{ transaction.amount|currency(transaction.currency) }} ({{ transaction.currency }})
  {{ transaction.paymentMethod.name }}
  {{ transaction.dateUpdated|date }} // could also format to get the time
{% endfor %}

The transaction 'type' column can hold the following values:

authorize, capture, purchase, refund

The transaction 'status' column can hold the following values:

pending, direct, success, failed

Some of those transaction types have a 'parent' transaction, for example, if you authorized a credit card, you would have a authorize transaction. When you capture that authorization you get a capture transactions whose parent is the authorize transaction.

{{ transaction.type }} // could return 'refund'
{% set parent = transaction.parent %}
{{ parent.type }} // could return 'purchase' or 'capture'

Let me know if you have further questions and I will improve the answer.


How do you delete entries from a frontend form?

It's going to be virtually identical to this answer, with the exception that you're posting to the 'entries/deleteEntry' controller action instead of 'assets/deleteFile' and you're posting the 'entryId' and the 'locale' of the entry you want to delete, instead of 'fileId'.

Note that this requires a logged in user with necessary delete entry permissions.


Associate child categories only to an entry

I managed to workaround this by creating my own custom fieldtype which is 99% the code from the Craft CategoriesFieldType, but with the only difference being I removed the call to craft()->categories->fillGapsInCategoryIds($categoryIds).

This works but I've yet to see if it causes any side-effects I need to worry about.


Generating pending image transforms stuck in process

More of a "How do I debug stuck tasks" answer, but it should help you.

Open up your craft_tasks table. You'll see one task in with a 'status' of 'running' and if you refresh the table several times, the 'currentStep' value for that task is no longer incrementing.  That's your stuck task.

Set that task's status to 'pending', and reload any page in the control panel to re-trigger the task.

If it gets stuck again, immediately go to your craft/storage/runtime/logs folder and check for a phperrors.log file.  If that exists, it will likely hold the error message for why the task is hung.

90% of the time, when a task gets stuck, it's because it has ran into some environmental limitation (PHP max_execution_time, memory_limit, etc.).

Update:

Just added a help article for this here: https://craftcms.com/support/stuck-tasks


How to replicate a Craft installation as a starting point

Relevant link: http://buildwithcraft.com/help/license-enforcement

But the TLDR is that purchases are tied to your craft/config/license.key file and the purchase will follow that file wherever it goes.

So as long as your replication script ignores that file, you'll get a fresh one tied to Craft Personal Edition the first time that Craft sees it's has an internet connection and you can make a new purchase.

Additionally, and regardless of edition, Craft will tie the license.key file to a domain when it thinks it's being run on a "public" domain.  Here is how we determine what is public.

Even if Craft gets that wrong (maybe you develop on public staging domaina.com, but the site will ultimately be on a public domainb.com) and Craft ties the license.key file to the staging domaina.com, the worst that will happen is that when you deploy the license.key file to domainb.com, you'll get a alert in the control panel saying something to the affect of:

"This license.key file is already in use on domaina.com.  Would you like to transfer it to domainb.com?"

None of the site's functionality will be affected.


How to move repeating code into an include template

That seo code will need to be in a block of its own.
Create a seo block in your _layout template and then wrap your seo code in your include template with block tags of the same name.


Express Forms Not Sending Notification Emails

I'm guessing if you update to the latest 3.x release of phpdotenv, the issue will resolve itself.

3.x added better support for environment variables running in multi-threaded environments.  You can read some background info here:
 https://github.com/craftcms/cms/issues/3631

Note that you'll likely need to update how phpdotenv is loaded in your public index.php file. You can read the upgrade guide here: https://github.com/vlucas/phpdotenv/blob/master/UPGRADING.md


Receive all locales with ElementAPI plugin

Here are some other similar questions and answers to this, but the short of it is that you could probably do it with something like using QueryBuilder to query the database directly (and bypassing Craft's APIs) or grabbing all site locales and looping through and re-querying for the entries on a per locale basis.

Both of them are pretty ugly and probably not that efficient in the context of the ElementAPI plugin.


PHP warning with composer on MacOS Mojave: Failed to open stream: No such file or directory

Composer symlinked the plugin from its physical directory into craft's vendor directory. The plugin directory as a result of this was not mounted into the docker container. Thus, craft was not able to locate the plugin as it wasn't mounted into my docker container. All I did to fix this was move the project(plugin) into craft's vendor director.


As long as you're already aware of the security implications. :)

Write a simple plugin that exposes a controller action where you pass in the user's ID to it.

All that action does is call:

craft()->userSession->loginUserById($userId);


Although I'm not in favor of the nuclear option in international politics, it works very fine and simply this case. Brad's suggestion of deleting the craft/vendor folder and composer.lock and then running
composer update
solved the problem immediately. Now I appreciate composer.


Element query - using "search" vs using field handle as query method

The search parameter gives you an entire range of search functionality, as explained in the docs at https://craftcms.com/docs/3.x/searching.html
Using a field handle as a parameter essentially specifies what the value of the field must equates to. How this is determined can vary, based on the field type, but in most cases it will be an exact match.
So in the following example, only entries with the exact plaintext field value something will be returned.
craft.entries.somePlaintextField('something')

If you dump the query's raw SQL then you will see this.
{{ dump(craft.entries.somePlaintextField('something').getRawSql()) }}

Outputs: SELECT ... WHERE ... AND (`content`.`field_somePlaintextField`='something') ...


How can I import existing users with passwords stored in a different format than Craft's hash format?

Short answer, it can't be done. Possibly with some extensive hacking, but I would highly caution against that.

Directly importing passwords isn't really possible, since the original passwords are unknown.
Adding a custom password column to the database is a bad idea, since Craft user/password management is pretty deeply embedded within the system.

Here's what I would recommend instead... Prompt your users to reset their passwords.

I know this idea doesn't seem ideal initially, but it is not unprecedented. People are used to changing their passwords occasionally, and will generally be very understanding about it. Many folks have dealt with systems that force them to change their password every 3 months, and everyone has forgotten a password at one time or another.

I recently had to do this for a website with several hundred users. We ported from EE to Craft, leaving the front-end visually identical. Here's the message we showed to users after the switch:

  Our login system has recently changed. Please note:

  If you haven't logged in since January 10th, you will be required to reset your password.


A solution is now available in the Sprout Forms documentation: Example > Pre-populating a Field.


Using Preparse field to display matrix blocks in Control Panel, limitations?

There may be a better answer, but this is what I have come up with. Using Control Panel JS, combined with Preparse field(s), I am adding characters in like this
{% for thing in entry.myMatrixField %}
  {{ thing.item }} - {{ thing.amount|number_format(2, '.', ',') }}^
{% endfor %}

And then using some basic jQuery to replace the ^ character with a line break. It's a bit clumsy, but it works. Now I can get Matrix fields to display in the control panel. Items, Budget line, Prices are all fields within my Matrix block. Just have to get them out separately.


Is your css file located in the /resources/ folder of your plugin? So your path should be something like:

<plugin folder>/resources/css/sitemaphtml.css

I've tried it myself and whilst you do get the /cpresources/ part of the Url in your markup, the CSS file is loaded on the front end.

EDIT: If you take a look in the docs, it says the following:

  By default, Craft will search for the resource file in its own
  craft/app/resources/ folder. If it can’t find the file there, it will
  check if the first segment of the resource path is set to a plugin
  handle. If it is, Craft will look for the resource file within that
  plugin’s resources/ folder.


When I want to add some features to my Craft site, do I need to modify the files in the craft/app folder?

Short answer... no!!! You don't ever want to make changes to the craft/app folder. Any changes you make in the app folder will be overwritten when you update Craft.

If you need any custom behavior, the correct way to do it is to write a custom plugin. Your plugin will be safe outside of the Craft core, and will survive any Craft updates intact.

Read up on the complete documentation for creating a Craft plugin. You can also download the Business Logic template to see what some basic components look like. Or even better, spin up a custom plugin using the fantastic Plugin Factory!


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

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


Just answering this for anyone that may come across this in the future as I have...

Could you reuse the group tag?

{% for block in entry.myMatrixField.group(<catgegory here>) %}
    ...
{% endfor %}

You have probably resolved it due to the age, but your answer would be helpful.


Assigned Files in entries won't get synced on localization

If you want this field to be synced (always same assets selected) across your locales you actually have to uncheck "This field is translatable".


Is it possible to view entries in admin panel list view with specific field?

You can use the cog at the bottom of the panel to choose which columns to show in the entries table

This then highlights which entries have the checkbox enabled:

Unfortunately, I don't think you can sort on this sort of column with core.

Some plugins may help here, if you want more control, e.g.

https://github.com/mmikkel/CpSortableCustomColumns-Craft

Or for a lot more options/control in this area:

https://zenbustudio.com/software/zenbu-craftcms


Updated To Craft 3, How To Delete Craft 2 Plugins

It partially depends on the plugin. The one guarantee you have is that there will be a row in the plugins table. Go ahead and delete that row.

Some plugins create 3rd party tables. For most of those plugins, it's probably safe to just delete those tables as well.

I know you can't go back in time, but... the best solution would have been to remove those plugins before updating. Virtually all Craft 2 plugins did a good job cleaning up after themselves in the database.

Based on your comment...

  "Form Builder 2, AmForms, Hacksaw, Shortener"

Form Builder 2 - Not very familiar with this, but looks like it has 5 tables. Probably safe to delete them.
AmForms - Another one with 5 tables. Probably safe to delete these as well.
Hacksaw - No DB tables
Shortener - No DB tables


How can I display a "pending" entry in my "_entry" template?

I'm assuming that when you defined your section, you checked the box which says this:

  Entries in this section have their own URLs

... and then filled out the relevant Entry URL Format and Entry Template values. The great thing about this technique is that it automatically populates the entry variable in your target template. Typically, this is the best way to go!

But there are occasions where this isn't the suitable solution. There are certain circumstances in Craft which, by default, can prevent non-active entries from being included. I suspect this is one of those situations.

Here is what I would suggest instead...

Uncheck the box which says "Entries in this section have their own URLs", and save.
Setup a dynamic route. This is basically what the aforementioned checkbox was doing for you.
Declare your route using the same pattern that you had previously setup in your section definition.
Within your template, manually set the entry value, based on the parameters passed through in the URL.

{% set slug = craft.request.getSegment(2) %}
{% set entry = craft.entries.slug(slug).status(null).first %}

Here's where this manual method differs from the automatic method... Specifying null as the status will return that entry regardless of what its status is. Otherwise, only an active entry could be returned.

Because you are now manually setting the entry value, you have enough control to specify that you really do want this entry, despite the fact that it's not currently active.


`Invalid argument supplied for foreach()` error

Looking at the code where your errors is occurring (line 46 of craft/app/fieldtypes/BaseOptionsFieldType.php), it looks like you have either a Checkboxes or Multi-Select field whose options setting is somehow set, but not set to an array. Not sure how it could have gotten into that state, but that’s the only thing that would explain your error.

Try re-saving any Checkboxes/Multi-Select fields (or if you have any 3rd party field types installed that might be extending Craft’s BaseOptionsFieldType, that would be even more likely the culprit), ensuring they have at least one option set.


How to use SSL for local development with Nitro?

Checkout Nitro 2, it now has full SSL support
https://craftcms.com/docs/nitro/2.x/commands.html#trust


layout file changes get deleted overnight

Craft isn't doing that automatically.

Guessing you've got some automated deploy that happens at midnight or some such and it's overwriting manual changes?


onSaveUser event - cannot redirect or access errors

As your code is running during an event, returning the request to the page has to be done a bit more explicitly than when you are performing similar behavior in a controller.

While I'm probably not the best person to explain this in detail, the code below gives one example I was provided in how you can set your route variables and end the request:

if ($errors)
{
    craft()->urlManager->setRouteVariables(array(
        'errors' => $errors
    ));

    $route = craft()->urlManager->parseUrl(craft()->request);
    craft()->runController($route);
    craft()->end();
}


Changing Content-Type on Sprout Forms custom endpoint

The Custom Endpoint integration currently is sending JSON as the request, but we could consider adding additional options there. I've opened a Feature Request if you'd like to add any more details there:
https://github.com/barrelstrength/craft-sprout-forms/issues/319

In general, the Custom Endpoint is best used when you control the other end of the request and control how you are receiving the data there. While it's possible that the Custom Endpoint can work with specific platforms, there may be several other considerations that will need to be addressed as you work toward a successful request such as authentication and the format of the fields being sent in the request - and in several cases, it may not be possible at all with the default settings or may require some additional configuration updates to get those things working.

For integrations with a specific platform that may require specific settings, it's Sprout Forms does have an Integrations API where you can add your own custom Integration for an editor to select and use.

In your case, that could mean that you create a Pardot Integration, configure your Pardot API credentials within your Craft and Integration module settings, and have the integration call out to the Pardot API to present the user fields or options that are retrieved from your Pardot account directly.


Can someone help me identify why my entry is invalidating?

getContent() will return the element’s ContentModel, NOT getContent()->merchant, which is just an attribute of the ContentModel—sorry for the confusion.

I’ve just posted a separate Q&A fully explaining what the ContentModel is used for here:

What is getContent() / the ContentModel, and how do I use it to get and set custom field values?

What you are experiencing is actually a slight bug in Craft’s validation logic. Relational fields have a feature where their data is not actually required to be in POST when saving an entry. If that’s the case (if their value in the ContentModel ends up just being null), then they will simply not make any changes to the element’s relationships - the field value will be left untouched.

However the ContentModel is not aware of that feature, and it’s the ContentModel that is currently in charge of enforcing Required Field validation. So, when it gets to your relational field, and finds that its value is null, it gives you a validation error rather than letting it slide.

So, you have two workaround options, if you want to keep the data the same, but need the field to be required:

You can actually set the value based on the current value:

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

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

If all you’re doing is changing custom field values (nothing entry-specific) and you’re comfortable skipping custom field validation altogether, you can just call ContentService::saveContent() directly, and pass in false to its second argument which tells it to skip validation:

$entry->setContentFromPost(array(
    // ...
    'merchant' => null, // Tells the relational field to keep the old value
));

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


500 error on installation since version 2.3

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

  RewriteBase /

after

  RewriteEngine On


add categories to sitemap plugin through the renderSitemap hook

You'll need to create a separate plugin, which adds the categories to the sitemap in response to the renderSitemap hook.

Here's what your main plugin file will look like. This should get you 90% of the way there; the rest is just organising a few files and folders, which is well-covered by the official documentation.

<?php

/**
 * SitemapCategories
 *
 * @package Craft
 */

namespace Craft;

/**
 * The main SitemapCategories plugin file.
 */
class SitemapCategoriesPlugin extends BasePlugin
{
    /**
     * Returns the plugin name.
     *
     * @return string
     */
    public function getName()
    {
        return Craft::t('Sitemap Categories');
    }

    /**
     * Returns the plugin description.
     *
     * @return string
     */
    public function getDescription()
    {
        return Craft::t('Adds categories to the sitemap.');
    }

    /**
     * Returns the plugin’s version number.
     *
     * @return string The plugin’s version number.
     */
    public function getVersion()
    {
        return '0.1.0';
    }

    /**
     * Returns the plugin developer’s name.
     *
     * @return string The plugin developer’s name.
     */
    public function getDeveloper()
    {
        return 'Your name here';
    }

    /**
     * Returns the plugin developer’s URL.
     *
     * @return string The plugin developer’s URL.
     */
    public function getDeveloperUrl()
    {
        return 'https://yourwebsite.com';
    }

    /**
     * Returns a faux schema version, so Craft doesn't attempt to run database
     * updates when the plugin version changes.
     *
     * @return string
     */
    public function getSchemaVersion()
    {
        return '0.0.0';
    }

    /**
     * Returns a boolean indicating whether the plugin has settings.
     *
     * @return bool
     */
    public function hasSettings()
    {
        return false;
    }

    /**
     * Returns a boolean indicating whether the plugin has it's own control
     * panel section.
     *
     * @return bool
     */
    public function hasCpSection()
    {
        return false;
    }

    /**
     * Adds all categories to the sitemap.
     */
    public function renderSitemap()
    {
        $groups = craft()->categories->getAllGroups();

        foreach ($groups as $group) {
            craft()->sitemap->addCategoryGroup($group);
        }
    }
}


I'm not sure I've got a good answer for you here.

Craft 2.x uses Guzzle 3.x for all of its outbound communications, so I'm not sure if it would be respecting stream_context_set_default at all.

If I recall, the last time someone brought this up, we looked into it and decided we needed to update to the latest Guzzle (5.x) to properly support it (they release quickly).

Unfortunately both Guzzle 4.x and 5.x introduced breaking changes to Craft.  So it'll have to be Craft 3.x before we add outbound proxy connection configuration options to Craft.

The only workarounds I can think of until then are to whitelist the IP address(es) of the Craft install to allow direct outbound access if that's possible.  If you can't do that, then maybe you can just get away with manual updates and let license checking silently fail.


I'm not sure what submissions is, but submits inside your loop is an array so you can access its values using submits['blog_name'].


Uploaded .gif only loops once instead of infinitely

We have the same problem here. I downgraded to version 2.6.2922 for testing purposes and the gif loops infinitely again. I suspect the bugfix in 2.6.2923
"Fixed a bug where animated GIF loop limits were not being respected." to be responsible. Unfortunately a downgrade on production is currently not possible for us, since the Schema version changed...


Is it possible to access Twig variables in a plugin variable using PHP?

You can’t access the current Twig variables (the “context”, as Twig calls them), from a Template Variable class, but you can access them with a template hook.

From your plugin’s init() function:

craft()->templates->hook('errorCheck', function(&$context)
{
    if (isset($context['errors']))
    {
        // do something with $context['errors'];
    }
});

From your template:

{% hook "errorCheck" %}

You can modify, delete, and create variables within that $context array if you want. And because it is passed by reference (that’s what the “&” does in “&$context”, you won’t need to actually return the array at the end of the function or anything; just make your changes to it.


You'd typically use the {% includeJs %} or {% includeJsFile %} tags within your page template, to specify your page-specific JavaScript, and then output everything in your layout template by calling {{ getFootHtml() }}.

Here's how your (very basic) page template might look in practice:

{# mypage.twig #}
{% extends '_layout' %}
{% includeJsFile "/assets/js/mypage.js" %}

And here's how your (equally basic) layout template might look:

{# _layout.twig #}
<!doctype html>
<html>
<head></head>
<body>

{# This outputs the JavaScript from mypage.twig #}
{{ getFootHtml() }}
</body>
</html>


How can I add custom validation rules to a new User registration?

At the time of writing the users.onBeforeSave event runs after validation, which means that we can’t add errors to the user easily.

The solution I’ve currently come up with is a plugin that adds custom validation rules to a user model, as well as a controller to handle the form submission.

Model

Firstly, I’ve extended the UserModel and added custom validation rules as needed.

<?php

namespace Craft;

class MyPlugin_UserModel extends UserModel
{
    protected function defineAttributes()
    {
        // Get the rules defined in UserModel
        $rules = parent::defineAttributes();

        // Add custom rules
        $rules['firstName'] = array(AttributeType::String, 'required' => true);
        $rules['lastName'] = array(AttributeType::String, 'required' => true);

        // If it’s a new user, require the password
        $isNewUser = !isset($this->id);
        if ($isNewUser) {
            $rules['password'] = array(AttributeType::String, 'required' => true);
        }

        return $rules;
    }
}

Controller

Secondly, I’ve created a controller action that will handle form submissions. This populates our custom user model with the input and runs the standard validate() flow.

<?php

namespace Craft;

class MyPlugin_UsersController extends BaseController
{
    protected $allowAnonymous = array('actionSaveUser');

    public function actionSaveUser()
    {
        $this->requirePostRequest();

        // Get input
        $post = craft()->request->getPost();

        // Create an instance of our model
        $user = new MyPlugin_UserModel($post);

        if (!$user->validate()) {
            // Add any errors from the validation to the user
            $user->addErrors($user->getContent()->getErrors());

            // Respond with errors
            if (craft()->request->isAjaxRequest()) {
                $this->returnJson(array(
                    'errors' => $user->getErrors(),
                ));
            } else {
                craft()->userSession->setError(Craft::t('Couldn’t save user.'));

                // Send the account back to the template
                craft()->urlManager->setRouteVariables(array(
                    'account' => $user
                ));
            }
        } else {
            // If all is well, run the default UsersController method
            craft()->runController('users/saveUser');
        }
    }
}

Template

For reference, here’s the action input in the template. Essentially, it’s just prepending the plugin handle before the default action.

<input type="hidden" name="action" value="myPlugin/users/saveUser">


If Most Recent Instance of a Block Contains X in Y Field Then Do Z

My answer is based on the assumption you only have one matrix module you want to compare, otherwise you would have to store your values in an array with the key as block.getType().handle or you would have to create multiple variables.

You want to create a variable that stores the value of your field if the block handle matches. So you check if your handles are equal and compare them

{% set latestBlockValue = null %}
{% for block in entry.matrix %}
    {% if block.getType().handle == 'referenceBlockType' %}
        {% if latestBlockValue is not null and latestBlockValue == x %}
            {# z #}
        {% endif %}
        {% set latestBlockValue = block.y %}
    {% endif %}
{% endfor %}


Get repeated events with the Solspace Calendar and Element API plugins

Unfortunately this won't be possible with Solspace Calendar since we are extending ElementCriteria with Calendar_EventCriteriaModel, which has a layer on top of it allowing us to build recurring events and return a padded list of events. We also return Event objects instead of EventModel objects, because working with Craft Dates makes it difficult/impossible for Calendar to have the dates it needs. Sorry :/


Try adding this to the beginning of your case study entry template:

{% if entry is not defined %}
    {% exit 404 %}
{% endif %}

Do you have a route set up for your case studies?

I've got routing set up on a client site that has the route /case-studies/* pointing to template /_cs/entry.twig

That makes it try to the load the template, whether or not there's an entry at all. So it needs the extra bit to check if the entry is real/published.


Allowing CRAFT_TEMPLATE_PATH in index.php from .env variable

If you add it after you load the dot env stuff in your public index.php file, it should work:

// Load dotenv?
if (file_exists(CRAFT_BASE_PATH.'/.env')) {
    (new Dotenv(CRAFT_BASE_PATH))->load();
}

define('CRAFT_TEMPLATE_PATH', getenv('CRAFT_TEMPLATE_PATH'));


Hard to know for sure without seeing some plugin code, but my guess is you'll want to use the TemplateCacheService's includeElementInTemplateCaches similar to how BaseTemplate's _includeElementInTemplateCaches does.


How can I have a dynamic/virtual attribute AND have as an attribute of the Model?

I think you're out of luck.  You can't go through the magic __get() logic and have a concrete get method and use both.  How will Yii/PHP know which one you're referring to when you do $model->fullName?


When should I run queue/listen instead of queue/run?

queue/run - should be used if you're going to manually execute this command via a cron job or such, because it runs any pending queue jobs, then exits
queue/listen - should be used if you want it to constantly poll (with a reasonable cooldown interval) for new jobs, and run them, because it runs a listen process that spawns a sub-process to run queue jobs as they come in

More here: Robust queue job handling in Craft CMS


Custom event not sending notification email

We got to the bottom of this issue and it turned out to be that the SproutEmail_SubscribeEvent::validateOptions() method was returning false. Updating this to ensure the options were being validated properly fixed the issue:

public function validateOptions()
{
  return true;
}

We've updated the docs and will also more clearly document this in the SproutEmailBaseEvent class in the next release.


Craft is the perfect CMS to handle everything you just pointed out.

Can Craft CMS handle bilingual sites? YES.

https://craftcms.com/docs/localization-guide

Is the Craft CMS admin available in French? YES.

https://craftcms.com/support/cp-languages

Can my client set up different user permission levels?** "YES".

Depending on your use case this will be doable. Then its just a matter of "how" your client wants to be able to do this. Craft supports dynamic user permissions creation so whatever your use case is I'm sure Craft will handle it with ease.


How to split the user login error message between username and password?

There is not a built-in way. If you take a look at the UserSessionService, you'll see that messages are returned based on an error code. When a username and password combination fail, it triggers this single message to be returned.


Sprout Email variables in custom fields aren’t replaced after update

This was a change introduced in v4.2.0 to address a security vulnerability. It was noted in the changelog and upgrade notes.
The Subject and Default Body will still render values dynamically but any personalization needed for custom fields would currently, as you've discovered, need to be handled in the templates.
I do have plans to review this more closely and see if I can find a workaround for custom fields, but for the time being, had to revert to the support above for security considerations.


As mentioned on Slack, the best approach to this currently is to set up all your variants and then use the plugin MultiAdd https://github.com/engram-design/MultiAdd to set up a form that can handle this.

Example code is in the ReadMe there.

It uses a single fast controller to update the cart all in one go, so there's no real speed penalty, and it raises events onMultiAddToCart etc. if needed too.


Move Icon Disappears from Categories editor

Ugh...never mind.  I guess I took it off structure without realizing it.


You can give a user or a user group the following permissions (on each section separately):

Edit entries

Create entries
Publish live changes
Delete entries
Edit other authors’ entries
Edit other authors’ drafts

If a user only can "create entries", but not "publish live changes", then he is not able to publish an entry (but he can create the entry).


How do I access the category of an entry with Element API?

Same as you would access it from a Twig template.  If you're positive there will always be one category selected, then this would work:

'transformer' => function(EntryModel $entry) {
    return [
        'category' => (string)$entry->categoryHandle[0],
    ];
},


Remove outdent & indent from Redactor2 "lists" button

I've managed to do this using a plugin which allows you to write CSS affecting the Craft CP.

Once: https://github.com/lindseydiloreto/craft-cpcss is installed, click Settings > Control Panel CSS and add this to the "Additional CSS" field...

.redactor-dropdown-outdent, .redactor-dropdown-indent {
    display: none !important;
}

Here's a screen shot:

This is what I end up with in Redactor...


After updating to Craft 2.5, standard and custom rich text (Redactor) fields disappear

It looked like my custom Redactor configuration files needed to be updated to be compatible with the latest version of Redactor that was included with Craft 2.5.  The This Craft support page described some of the changes, but these did not fully fix my issue.

I figured out that the structure of "formattingAdd" configuration had been updated. Once I followed the format described on the Imperavi site, the fields started displaying again.

Version 1 formattingAdd syntax:

formattingAdd: [
    {
        tag: 'p',
        title: 'Disclaimer',
        class: 'disclaimer'
    },
    {
        tag: 'a',
        title: 'Secondary CTA',
        class: 'btn btn-default'
    }
]

Version II formattingAdd syntax:

formattingAdd: {
    'disclaimer-add': {
        title: 'Disclaimer',
        args: ['p', 'class', 'disclaimer', 'add']
    },
    'secondary-add': {
        title: 'Secondary CTA',
        args: ['a', 'class', 'btn btn-default', 'add']
    }
}


Using `getPrev` and `getNext` with entries sorted by SuperSort plugin?

It won't work with getPrev and getNext, as they only work with ElementCriteriaModels and not with an array of Entry models.

But that is what you get returned from the plugin. Supersort converts your craft.entries ElementCriteriaModel into an array of Entry models. This is necessary so that it can do the sorting.

The only workaround I know of would be to get the IDs of your supersorted entries and pass them to the ID param of a new ElementCriteriaModel.

{% set entries = craft.entries.section('sectionName').type('entryType') %}
{% set entriesSorted = entries|supersort('natsortAs', '{title}') %}

{% set entryIds = [] %}
{% for entry in entriesSorted %}
    {% set entryIds = entryIds|merge([entry.id]) %}
{% endfor %}

{% set arrowCriteria = craft.entries.id(entryIds).fixedOrder(true) %}

Now you have an ElementCriteriaModel arrowCriteria, prepared to get entries in the desired sort order. So now you can use arrowCriteria with your entry methods.

{% set prevEntry = entry.getPrev(arrowCriteria) %}
{% set nextEntry = entry.getNext(arrowCriteria) %}

{% if prevEntry %}
    {{ prevEntry.title }}
{% endif %}

{% if nextEntry %}
    {{ nextEntry.title }}
{% endif %}


FormBuilder - PHP notice Trying to get property of non-object

I had the same issue. My problem stemmed from the fact that I had put all of the form fields that I created into the field layout for my form page.

I was used to putting all the fields directly on to the page. Once I removed all the form fields from my field layout, I was able to successfully access the page to manage my content.

It seems as though your fields for forms should be treated separately and not put directly into the page. They should be added through the formbuilder plugin.


There is a Quick Post widget that allows you to create entries from the Dashboard page of the Control Panel.

A New Entry button is available from the entries index pages located at the top right, e.g. http://
example.com/admin/entries/news


If I'm understanding you correctly, what you're looking for is the RelationsService's saveRelations() accessed via craft()->relations->saveRelations().

You pass in your $fieldModel, $source ElementModel and an array of $targetIds that you want to created the relations to.


You'll need to add more details about your current setup for a more specific answer.

In general, adding a number to the Meta Title and Meta Description is probably not a good approach to solve your problem of duplicates. Search engines score your page based on how relevant your content is. Adding a number, unless it has some meaning (perhaps a date for an event, tax form number, or 241543903), is just going to be noise and not help your page rank in any meaningful way.

Consider what other data you have in your posts. Can you add the name of a category some items are in? Can you add the name of a User that posted the content? Often there is a way to take a generic page and add a second dimension of data to make it more meaningful.

Generic Name - Category 1 - Site Name
Generic Name - Category 2 - Site Name

Alternatively, if the pages really are not meaningful, consider pointing search engines to a more meaningful canonical URL. For example, if you have a paginated index page, sometimes all the secondary pages will appear to have the same metadata.

In these cases you can add the canonical meta tag to point back to the primary page as the one that should be recognized by search engines.

https://website.com/section (points to self with metadata)

https://website.com/section/2 (points to main section page with metadata)
<link rel="canonical" href="https://website.com/section" />


Is the physical web server inside your network as well? As mcclaskiem mentioned,  check to see if the IP address is within the subnet of your network and then allow access that way.

You may want to have the web server listen on another hostname that's not accessible outside the network and allow access to that vhost unconditionally (but do that at the firewall level). The would be the securest way to allow access within your network without logging in. IP addresses can be spoofed with varying threat so I'd be wary of allowing anyone to authenticate via just an IP Address if your webserver is located off-premise.

Dealing with google auth on the "other side" would obviously require a plugin for people attempting to connect outside the network.

Here's another thread for further reading.


This is one part of a bigger switch case statement for a Craft Matrix field.

My block is called newFeatureVideo.
my field is called video.

{% case "newFeatureVideo" %}
  {% for items in block.video.all() %}
    {% set item = craft.embeddedAssets.get(items) %}

{{ item.title }}

  {% endfor %}


Try replacing your "require" section with this in your composer.json file:

"require": {
    "craftcms/cms": "^3.0.18",
    "vlucas/phpdotenv": "^v2.4.0",
    "craftcms/redactor": "^2.1.5",
    "dolphiq/craft3-forms": "^1.1.0",
    "craftcms/contact-form": "^2.2.2",
    "craftcms/guest-entries": "^2.1.3",
    "nerds-and-company/schematic": "^4.0.14"
  },

Then, if you have Composer installed from the command line, run composer update from your project's root and let it finish.


Why are my template filenames showing up in Google Analytics

From my testing it appears that this is an issue with Google's universal analytics.

Based off of Clive's recommendation, my solution what to change

  ga('send', 'page view');

to

  ga('send', 'pageview', {
   'page': '/{{entry.slug}}',
   'title': '{{entry.title}}'
  });

This seems to be holding up well.


User not being logged out when visiting {{ logoutUrl }} link

Turns out this was caused by me setting a "Cache-Control: max-age" header which I was testing with Google Page Speed and I forgot to move it. This meant the browser was caching everything including the session cookie.


Can you call a controller method from within a plugin/module in Craft 3?

Based on your goal, I don't recommend taking this approach for the technical debt reasons in my comment, however your actual question is still a valid one. You can call any controller's method from a plugin/module like this:
Craft::$app->runAction('users/save-user');


Depends on your requirements, but seems like you'd just be able to use the standard PayPal checkout button for this, no?

https://www.paypal.com/us/webapps/mpp/paypal-payments-standard


Category query very slow on multilingual site

It's hard to know for sure without seeing your query profile output, but try eager loading your ports field like so:

{% set categories = craft.categories({
    group: 'locations',
    limit: null,
    with: ['ports']
}) %}


Auto add Images to entry after ftp to server

Since it sounds like you are using a third-party plugin for the initial import, you'll need a new plugin to handle the ftp uploads.
This new plugin would need to perform the following:

Basic control panel page, or Controller action for firing off the processing
Get the list of new images files from the FTP directory
For each file:

Parse the file name to get the associated vehicle stocknumber
Query your vehicle entries based on the stock
Use the Assets Service  (https://craftcms.com/classreference/services/AssetsService) to
create and store the asset appropriately
Save the associated asset to the Vehicle Entry

At the end of the run, archive/remove the original uploaded files
Email the list of stocknumbers you have image files for but not existing entries (using EmailService)

To further optimize the process/queries you could query all vehicles first and pull them out of an array by the stocknumber (instead of querying the DB each file).

If you wanted to automate the process you could even build a task-listener to fire off your image-association plugin when it sees new images have been FTP'd to the vehicle image upload directory.


Craft CMS 3 error in Windows installation process

You'll get that error (regardless of OS) if the SECURITY_KEY variable isn't set in your .env file: https://github.com/craftcms/craft/blob/master/.env.example#L5

See this step in the install docs: https://docs.craftcms.com/v3/installation.html#step-3-set-a-security-key

If you run the craft setup terminal command, it will generate that key for you, but depending on how you install Craft, you can also manually set it.


Disable "dynamic links" in rich text fields

and we understand what the purpose is of this additional #entry:3962:url, but is there a way to disable this?

Currently not.  You'd need to write a Craft/Redactor plugin that used the addRichTextLinkOptions hook to do something similar to what the default "Link to an Entry" does, but with your own custom logic.


How to exclude multiple email addresses from an order query

Agree it'd be nice if it worked that way... I'm not sure why it doesn't, but replacing it with a regular where clause and not in works ok:

$order = Order::find()
    ->isCompleted(true)
    ->where(['not in', 'email', ['nobody@example.com','no@example.com']])
    ->all();


Query only returning 100 records at a time?

Craft imposes a default limit of 100 for element queries. To disable this you need to specify a limit of null.

$criteria->limit = null;


Is it possible to change the title of "Quick Post" dashboard widgets?

You can use this Control Panel JS plugin to change the info.

Just copy the cpjs folder in the craft/plugins/ folder and the plugin should appear in Settings->Plugins. Install it and add your code in the textarea displayed at the bottom.

Now with your title:

In the dashboard, each widget has an ID like widget1, widget2, etc; get it with the dev tools.

Then try the following code changing the corresponding widget number:

document.getElementById("widget1").childNodes[3].innerHTML = "new_title";


You can't do this with the criteria parameters offset and limit. I would suggest to first get all the IDs of your section and then use Twig's handy cycle function to get those entry IDs you're interested in.

That function starts to read an array from the beginning again, when it reaches it end, so that's exacly what you need here. So when you want to get the 8th element of an array of length 7, it returns the first element (monday)!

The first element / ID of your array is in position 0, so I sustracted 1 from the week day number before passing it to the cycle function.

{% set allIds = craft.entries.section('schedule').ids() %}
{% set nextIds = [] %}

{% set start = now|date('w') - 1 %}
{% set end = start + 2 %}

{% for i in start..end %}
    {% set id = cycle(allIds, i) %}
    {% set nextIds = nextIds|merge([id]) %}
{% endfor %}

{% set entries = craft.entries.id(nextIds).fixedOrder(true) %}


Redactor deleting   and other inline markup

Imperavi fixed this in Redactor II 1.2.2, and we included that update in Craft 2.5.2763.


Using services/records etc in migrations

Are there technical reasons for this recommendation, or is it something you'd just rather not support?

It's more along the lines of it's something you're not going to want to support.

The problem is that things like services and records change over time.  Methods get renamed/deleted, attributes change, parameters change, etc.

By using them in a migration you're assuming that the methods you're calling and the attributes you're using are going to be there for the rest of time and that's not necessarily going to be true.

A year from now if someone tries to run that migration, there's a chance those services and records are going to look very different and the migration is going to fail because it was written for what the service/record looked like a year ago.

You're much better off thinking of migrations as little self-contained applications with as few dependencies on external Craft classes as possible.


How do I handle named route variables passed to a controller?

To quote @Brandon from here:

  Yep you just need to include a $variables argument in your controller
  function, typeset to an array:

public function actionArchive(array $variables = array())
{
    $variables['year'] ...
}


Filter Entries by Category fields & refresh URL and list with AJAX

First you need some HTML/Twig logic to display your categories

    {% for category in categories %}
        <input data-id="{{ category.id }}" data-slug="{{ category.slug }}" type="checkbox" class="category-filter">{{ category.title }}
    {% endfor %}

    Submit

Then some Javascript logic to make an ajax request, keep in mind you need some variables for csrf protection

window.csrfTokenName = "{{ craft.app.config.general.csrfTokenName|e('js') }}"
window.csrfTokenValue = "{{ craft.app.request.csrfToken|e('js') }}";
window.siteUrl = '{{ entry.getUrl() }}';

$(document).ready(function () {
    $('#submit').click(function (e) {
        e.preventDefault();
        var checked = $('.category-filter:checked');
        var ids = [];
        var slugs = [];
        $.each(checked, function (index, item) {
            ids.push(item.dataset.id);
            slugs.push(item.dataset.slug);
        });

        var data = {
            action: 'plugin-id/controller-id/action-id',
            ids: ids
        }
        data[window.csrfTokenName] = window.csrfTokenValue

        var newUrl = siteUrl + '?location=' + slugs.join();
        $.ajax({
            url: '/',
            data: data,
            type: 'POST',
            dataType: 'json',
            success: function (response) {
                console.log(response);
                history.replaceState({}, '', newUrl);
            }
        });
    })
});

And finally your Controller

public function actionIndex()
{
    $ids = Craft::$app->getRequest()->getBodyParam('ids');
    $entries = Entry::find()
        ->relatedTo($ids)
        ->asArray()
        ->select(['elements.id', 'title'])
        ->all();

    return $this->asJson([
        'entries' => $entries
    ]);
}


Anyway to extend Craft Entry query search in Craft 3

The "proper" way to access the element query that gets generated is through a plugin via the ElementQuery's query and subquery properties.

It looks like you're doing a Haversine algorithm to calculate distance between a latitude and longitude.  There's are some similar plugins that already do this you can use as an example.

For example: https://github.com/ethercreative/simplemap/blob/v3/src/services/MapService.php


Re-render Widget after column number changes

I found an answer that works for me at least..
Since I render my widget via Javascript and not via PHP/Twig I can use this

$(document).on("click", ".colspan-picker a", function(){
    var container = $(this).parent().parent().parent();
    widgetID = container.data("id");
    sRGoogleAnalyticsRerenderChart(widgetID);
});

.colspan-picker a is the element for columnchange and its parent().parent().parent() has a data-id of the widget container


List entries related to several categories

Not sure if this is still what you are after (I removed a lot of parameters), but basically this gets the one (!) category with the unique (!) slug you request from the URL and then lists the entries related to it:

{% set categorySlug = craft.request.getLastSegment() %}
{% set category = craft.categories.group('compositions').slug(categorySlug).first() %}

<h1>{{ category.title }}</h1>

{% set entries = craft.entries.section('contenuCompositions').relatedTo(category) %}

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


Display entries filtered by one or two related entry fields ordered by "dateUpdated"

If I understand your structure correctly, something like this should work. First grab the ids, merge them (if they don't already exist in the id array), then query for entries based on ids with sort order defined.

{% set programs1 = craft.entries.section('programs1') %}
{% set programIds = craft.entries.section('news').relatedTo(programs1).ids() %}
{% set programs2 = craft.entries.section('programs2') %}
{% set program2Ids = craft.entries.section('news').relatedTo(programs2).ids() %}

{% for id in program2Ids %}
    {% if id not in programIds %}
        {% set programIds = programIds|merge(id) %}
    {% endif %}
{% endfor %}

{% set programEntries = craft.entries.section('news').id(programIds).order(dateUpdated).limit(4) %}

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


Get image from related entries asset field

Got a solution that is cleaner than nested for loops.

{% set myRelatedImage = entry.relatedImages.first %}

then I can do

<img src='{{ myRelatedImage.images.first.url }}'>

My use case was slightly different. I have a bunch of sermons entries that are related to a series entry. It's the series entry that has the image attached.

This worked very nicely.


redirectToPostedUrl with object (Model) passed to it and keep template resolving

Maybe not the prettiest URL, but I think the simplest solution would be to redirect to something like:

http://web.dev/success?id=ch_5GW2RFTNvW8qeR


Do another call to craft.entries when you loop through the "area" entries and include the section and relatedTo params:

{% for entry in searchEntries %}
    {% set videos = craft.entries.section('videoSectionHandle').relatedTo(entry) %}
    {% for video in videos %}
         {# Output video here #}
    {% endfor %}
{% endfor %}

If you're trying to maintain a one-to-one relationship it might make sense to limit the relation query to one result, and to include the first param to return the first (and only) result and not an array – then you can omit the nested for loop:

{% for entry in searchEntries %}
    {% set video = craft.entries.section('videoSectionHandle').relatedTo(entry).limit(1).first() %}
    {{ video ? #--Output video here--# }}
{% endfor %}

You can read more about the relatedTo param here, it's pretty powerful.


Unverified emails blocking user registration

I'm not sure that I agree with your analysis.  At a minimum maybe it's a feature request with a config setting to change the behavior.

But if you're really concerned about the behavior, you can currently set the purgePendingUsersDuration config setting to something like 24 hours so they don't hang around very long.


How can I programmatically add a tab to entry type?

I eventually figured this out. Here's the code that's working for me:

$newFields = array(
  0 => '12', // $field->fieldId
  1 => '15'  // $field->fieldId
);

// First we get all sections and loop through them
$allSections = craft()->sections->getAllSections();
foreach ($allSections as $section)
{
  // Then we get all EntryTypes of each section and loop through those
  $sectionEntryTypes = $section->getEntryTypes();
  foreach ($sectionEntryTypes as $entryType)
  {
    // Grab the current layout and tabs
    $currentLayout = $entryType->getFieldLayout();
    $currentTabs = $currentLayout->getTabs();

    // This will the array passed to assembleLayout
    $postedFieldLayout = array();

    // Loop through each tab and build our array
    foreach ($currentTabs as $tab) {
      $fields = $tab->getFields();
      foreach ($fields as $field) {
        $postedFieldLayout[$tab->name][] = $field->fieldId;
      }
    }

    // Append the new fields we want to show to that array
    $postedFieldLayout['newFields'] = $this->newFields;
    $requiredFields = array();

    // Assemble the layout
    $fieldLayout = craft()->fields->assembleLayout($postedFieldLayout, $requiredFields);
    $fieldLayout->type = ElementType::Entry;
    $entryType->setFieldLayout($fieldLayout);

    // Save it
    if (craft()->sections->saveEntryType($entryType))
    {
      Craft::log('Successfully appended fields.');
    }
    else
    {
      Craft::log('Could not append the fields.', LogLevel::Warning);
    }
  }
}


For loop does not display all entries in section

Craft has a default limit of a 100 elements returned via an ElementCriteriaModel. To pull all elements, you'll need to explicitly set limit to null:

{% for post in craft.entries.section('posts').limit(null) %}
    ...
{% endfor %}


Multi-lingual site navigation made of singles, channels and structure

I have one main structure "pages" and got rid of all single sections. I also gave each channel's index page an entry in the structure (good for URL translation). Then I added some entry types to it (you can also link templates to them) and created my site navigation like in my example code below.

This allows you to translate the slug of the index pages in the CP and you have access to localized URL (page.getUrl) and page title variables (page.title) in your nav template.

Only one level of hierarchy I need. If you have to go deeper, the nav tag's waiting for you! ;)

{# Get top-level entries in pages structure #}
{% set pages = craft.entries.section('pages').level(1) %}

        {# Loop through entries (= pages) and list the links #}
        {% for page in pages %}

                {{ page.title }}

        {% endfor %}

        {# Include links to switch locales #}

            {% include '_includes/language_switch.html' %}


I may be mistaken, but I feel like a standard multi-environment configuration should work for you in this situation... specifically the use of environment-specific variables.

When you setup your multi-environment configuration, just set one up for each of your domain names. You would include something like this in your config/general.php file...

'my.first.domain' => array(
    'environmentVariables' => array(
        'siteUrl' => 'http://my.first.domain/'
    )
),
'my.second.domain' => array(
    'environmentVariables' => array(
        'siteUrl' => 'http://my.second.domain/'
    )
),

Once you've got that setup, login to your Control Panel and go to:

  Settings > General

Change the value of Site URL to be "{siteUrl}".

Now, you can easily use any of these variations in your template:

{{ siteUrl }}/contact-us
url('contact-us')
siteUrl('contact-us')

It's a little tricky to explain the relationship between those three variations of "site url", but here's the gist of it...

When you set an environment-specific variable in your config file, it can be parsed by Craft (in certain circumstances) with the syntax {siteUrl}. Note the single set of curly braces, and the lack of spaces between the variable name and the braces.
The "Site URL" setting in your CP is capable of parsing out environment-specific variables. So when you put "{siteUrl}" in there, it represents whatever you put in your config file.
Now, when you use {{ siteUrl }} in your templates, it uses whatever value is represented by the "Site URL" value in your CP. Since we just told that field to use the environment-specific variable, that's what will be parsed through to the front-end.

In my example, I also mentioned url() and siteUrl(). These two functions will automatically prepend the "Site URL" value to whatever string you specify.

The difference between the two only really matters if you're rendering a template in the Control Panel (using a plugin). url() will prepend the entire site url, including the /admin/ segment... meanwhile, siteUrl() will only prepend the base site url.


There are multiple ways to solve this:

Native:

Twigs url_encode filter:

{{ "apples and carrots"|url_encode }}
{# outputs "apples%20and%20carrots" #}

Twigs replace filter:

{{ "apples and carrots"|replace(' ', '-') }}
{# outputs "apples-and-carrots" #}

Plugins:

Twig PCRE Filters - Plugin:

{{ "apples and carrots"|preg_replace('/ /', '-') }}
{# outputs "apples-and-carrots" #}

Low Regex - Plugin:

{{ "apples and carrots"|regex('/ /', '-') }}
{# outputs "apples-and-carrots" #}

Slugify - Plugin:

{{ "apples and carrots"|slugify }}
{# outputs "apples-and-carrots" #}


How to use the Element API endpoint without wrapping it in data object

Use the config setting 'first' => true and wrap the endpoint in a function

like this:

'api/link' => function() {
    return [
        'elementType' => 'Entry',
        'first' => true,
        'criteria' => ['section' => 'mysecton'],
        'paginate' => false,
        'transformer' => function(EntryModel $entry) {
            return $something;
        }
    ];
}


You're probably looking for a combination of:

craft()->userSession->login()

or

craft()->userSession->loginByUserId()

along with setting the userSessionDuration config setting to a really high value.


How delete a user session with the element api?

You can end a user's session with the craft()->userSession->logout(), method, which the UserSessionService class inherits from the CWebUser class.

So, your userLogout function would look like this:

function userLogout(){
    if (craft()->userSession->isLoggedIn()){
        craft()->userSession->logout(false);
    }
}

Additional information

Passing false to the logout method tells Yii not to "destroy" the session, and mimics the call in Craft's UsersController::logout method.

According to the Yii documentation, destroy "frees all session variables and destroys all data registered to a session." I'm unclear why Craft chooses not to destroy the session.

The UsersController::logout method also includes a few cleanup tasks, but those seem to be duplicates of the tasks performed in the UserSessionService::afterLogout method.

The afterLogout method is called from the craft()->userSession->logout() method, so you shouldn't have to worry about this manual cleanup.


With a mixture of the permissions you mention above and user groups, you should be able to use the Workflow plugin to get the results you are looking for.


How can I display the Discount Value onSale of Products

I haven't done this myself, but I see two ways to get the percentage:

Take the product.defaultVariant.saleAmount and use maths in twig to work out the percentage - that should definitely work.  Twig math is a good general solution if you can't get the numbers you need directly from Commerce. See:

http://twig.sensiolabs.org/doc/templates.html#math

However, I think you can use

 {% set sales = craft.commerce.getSales() %}

...to get all your SalesModels.

(see /craft/plugins/commerce/models/Commerce_SaleModel.php) as this model is not really documented yet it seems.

You'd loop through those and get the particular sale you're after (e.g. by id).  Then, it appears there is code in there to  getDiscountAmountAsPercent to get what you're after....however while DiscountModel has an attribute of percentDiscount on it, SaleModel does not appear to so I don't think you can get at it directly in your templates currently.

Unfortunately I am a bit pushed for time in terms of actually trying it to see.  But Twig maths will do it for sure if you get stuck with a more direct approach!


asset.first().getUrl('transform') not working for s3 asset - Craft CMS 2.6.2980

Turns out you need to have the URL prefix set under the Asset Settings in order to call .getUrl()

Once I added this, my transforms began working.


This is because I was on a category page not an entry page, so the entry variable didn't exist!


This is how to "translate" a slug:

{% set enSlug = 'work' %}

{# Get the ID of an entry with that english slug #}
{% set enId = craft.entries.slug(enSlug).locale('en').first().id %}

{# Use the entry ID to get the german slug #}
{% set deSlug = craft.entries.id(enId).locale('de').first().slug %}


Redirecting with http status code doesn't render template

{% exit 403 %} seems to be the answer! Seems so obvious now... facepalm


Looping Entries in Super Table, display row details

This can be done, but it does require additional calls to query this information. It might be more efficient to hard-code this text in your template, unless you really want to make this text dynamic.

There's two concepts here. When you call entry.relatedArticleLinks you're fetching Super Table blocks that are related to the entry in question. Calling englishLinks on each of these blocks will return the content for this field - nothing about the field definition itself, such as the handle, name, or settings - just the content.

What type of field is englishLinks?

If you wanted to grab the field definition as well, you can by calling:

{% set field = craft.app.fields.getFieldByHandle('relatedArticleLinks') %}
{% set blocks = craft.superTable.getSuperTableBlocks(field.id) %}
{% set fields = blocks[0].getFields() %}

{{ fields.englishLinks.name }}


(I'm writing this in case someone comes across the same problem)

As @MatsMikkelRummelhoff pointed out, I still had to change the URL's format settings to team/{slug}


Best way to effect part word searching by default

This sounds like a good approach and could be done using a twig filter on your search string.

Here are the first two lines of the example from the docs:

{% set query = craft.request.getParam('q') %}
{% set entries = craft.entries.search(query|customFilter).order('score') %}

In this example query is now modified by customFilter and can be updated in your Twig filter to behave however you like.


Nested IA Structure - What's the best way to get it set up?

Lots of question so I'll describe how I would do it more or less. Ask if you want more info.

/ - single page type.

/about - single page type.

/industries - single page type.

/about/{slug} - structure page type (structure offers nested entries)

/industries/{slug} - structure page type

You cannot create /about entry within structure with slug like /about/{slug} - thats why /about is a seperate single page type page.
Of course you can create single structure with {slug} as url - then /about and /industries could be created within structure section. Note: with many entries it is harder to handle in CP.

About structure would have following entry types:

bios
contentPage
contactForm

CP Section edit screen

CP Entries:

about/_entry template would look like this:

{% extends "base_template" %}
{% block body %}
    {% switch entry.type %}
        {% case "bios" %}
            {% include "about/bios" %}
        {% case "contentPage" %}
            {% include "about/content_page" %}
        {% case "contactForm" %}
            {% include "about/contact_form" %}
    {% endswitch %}
{% endblock %}

or it could be (but I prefer first approach)

{% extends "base_template" %}
{% block body %}
    {% include "about/" ~ entry.type %} (filename == entry type)
{% endblock %}

Channel/structure sections can have multiple entry types. All of them use template defined by Entry Template - thats why we include other templates based on entry type.

/about, /industries single page template:

To fetch data from all subpages you can either hardcode it to fetch entries from section like this:

{%- set entries = craft.entries({
    section: 'aboutSection',
    order: 'postDate desc',
    limit: 20
}) -%}

{%- for entry in entries -%}

{{ entry.title }}

    //use switch to display data specific to entry type
{%- endfor -%}

Or you can add entry field (lets call it subpages) to the page and display it like this:

{%- for entry in entry.subpages -%}

{{ entry.title }}

    //use switch to display data specific to entry type
{%- endfor -%}

With field approach you can change content without changing the code.

Here is hybrid - use query when no entries assigned to entry field:

{%- set entries = entry.subpages %}

{% if entries.total() < 1 %}
    {%- set entries = craft.entries({
        section: 'aboutSection',
        order: 'postDate desc',
        limit: 20
    }) -%}
{% endif %}

{%- for entry in entries -%}

{{ entry.title }}

    //use switch to display data specific to entry type
{%- endfor -%}

Similar industries section:

CP Section create page

CP Entries:

UPDATE

Industries Overview entry type template

Here you could query items like so:

{%- set entries = entry.chrildren -%}
{%- set entries = entry.chrildren.descendantDist(n) -%} n levels below entry
{%- set entries = entry.chrildren.type('content') -%} specific type of children
{%- set entries = entry.chrildren.type('content').with(['field', 'field']) -%} .with() helps reduce SQL queries

.children returns ElementCriteriaModel same as craft.entries so all methods here apply.

Or again you can add entry field and display specific children.

UPDATE 2

Q: In the case of the Medical > Portfolio being a single entry type WITHIN a structure, I'm assuming individual Portfolio Items would be housed within a Channel of their own?

Yes, that is one approach. To achieve this you would create a new section with URLs disabled (unless you want portfolio items to be accessible via URL - ex. separate page) like so:

Then you just query those items. Oh, I used Stucture instead of Channel - in addition to nested entries, Structure allows to reorder entries.

{% switch entry.type %}
    {% case "medicalPortfolio" %}
        {%- set entries = craft.entries.section('medicalPortfolioItemsSection') -%}
        {% include "industries/portfolio" with {"entries": entries} %}
        ...
{% endswitch %}

Important thing here is to create additional entry type per industry so you can query proper portfolio items. Also new section per industry. It is not good solution here because we duplicate things.

Another way is to use Matrix field to define portfolio item. This way you just use Portfolio entry type with Matrix field within Industries structure.


Craft 3: When querying for Matrix blocks in a plugin, how do you sort by a custom field?

->orderBy('fieldHandle')

or

->orderBy(['fieldHandle' => SORT_DESC])

But you have to make sure the field is sortable, otherwise it won't work


Caching and Memory problems. What is best caching method

Sure. In my experience it's often better to cache individual entries, rather than whole pages, if the entries have a lot of relations to other elements. It's very resource intensive in Craft to figure out for instance if an image or entry relationship exists. And the more relations you have, the more frequent the cache would break.

The project I'm currently working on has a lot of different landing pages with entry items that have a ton of different images and relations. So I have A LOT of this going on for every single entry in a landing page:

{% if article.commentator | length %}
  {% if article.commentator.first().profileImage | length %}
    {% set listImage = article.commentator.first().profileImage.first() %}
    ...
  {% endif %}
{% endif %}

I found that when I cached the whole page, it would break often, resulting in a serious performance hit. I changed my code to cache individual entries. The difference in load of the page as a whole was small, but the actual impact in percieved performance was huge. In a positive way. :)

I also use the same generated HTML on a lot of different pages, so I also made the caching of these items globally. I create a key that is unique for the different options the block could have. The final cache tag looks something like this:

{% cache globally using key ("article-grid-item-" ~ article.id ~ "-" ~ gridType ~ "-" ~ modifier ~ "-" ~ craft.config.environment) for 3 hours unless craft.config.templateCacheDisabled %}
...
{% endcache %}

But the only way to figure out which would be better is to test it on your project. All builds are different, and as far as caching is concerned, there are no simple answers. ;)

And... I also wish P&T would make this easier/less resource consuming: {% if entry.image | length %} :)


Custom ElementType empty getSource criteria?

You can set it to ':empty:', as mentioned in the DbHelper::parseParam() documentation.


I think you should change ['SORT_DESC'] to [SORT_DESC]. See this tweet for an example. SORT_DESC is a PHP constant, not a string.


Using a field multiple times in a single template

The only solution is to create yet another Grid field that uses the same twig code for rendering only to use it again on the same side.

Do you need to enforce that structure or is it a "soft" restriction (meaning things won't go south if the blocks get turned around)?

If it were me, I would treat Matrix more or less like a site builder.  [some hero image] and [other stuff] could also be blocks in that matrix, alongside full column and half column, you just need the appropriate code to "close up" the grid when necessary.

You would have different blocks (like Grid, Hero Unit, Ad space, etc.) and then when building the page, just insert them in the appropriate spots.

That's the canonical use of Matrix of course. If you need full control over how things are presented you don't necessarily have to build out the page in the order the blocks appear in. If you name various blocks you could filter by block type and then spit out only the blocks that would appear in that area. For example, even if there is only one hero unit, you can specify it should only appear once and then spit out the hero where it needs to go (say at the top).

If you're doing this for a client, it might be helpful to number the blocks so they put the blocks in the intended order to avoid surprises but with matrix it's pretty open ended which might be less likely what you're looking for.

Ideally we should be able to have some "default" blocks and lock 'em in place so they can't be moved or disabled... maybe in a future version of Craft.


Nesting blocks - is the following problematic?

Yes, see the block tags docs. http://twig.sensiolabs.org/doc/tags/extends.html#block-nesting-and-scope


Output values from all entries in a specific section EXCEPT those with a specific category id

You can get the entry IDs that have are related to the category and then exclude them from the all the entries.

{% set entryIdsWithCategory =
craft.entries.section('driverPositions').relatedTo('7192').limit(null).ids() %}

{% set entryIdsWithoutCategory = craft.entries.section('driverPositions').limit(null).ids()|without(entryIdsWithCategory) %}

{% set entries = craft.entries.section('businesses').limit(null).id(entryIdsWithoutCategory).order('state, city') %}

{% for entry in entries %}
    <option value="{{entry.url}}">{{ entry.state }} - {{ entry.city }}</option>
{% endfor %}


How can I utilize existing UI for my plugin's control panel views?

Have a look in craft/app/templates for tons of great, easily-reusable examples that make up the existing control panel! They may not be documented, but there's a whole lot of quality stuff there.

You may also want to consider using macros from craft/app/templates/_includes (Craft TemplatesService doc, Twig macro doc), which will go a long way toward good DRY templates.

Bonus: this is also a great way to learn clever ways of doing things in Twig, like breadcrumbs for example. P&T builds excellent stuff, so there's lots to learn from and steal whether it's for the control panel or the front end.


Adding active class to globally cached navigation

Yes, you can!

The first thing you need to do is to add the entire cached content into a single variable:

{% set navigation %}
    {% cache globally for 3 years %}
        {# YOUR CACHED CONTENT #}
    {% endcache %}
{% endset %}

Then you need to add some dummy placeholder tags on your
 tag and your  tag which then can be used by |replace filter to make the replacement.

For

For  (You need to modify this for each different entry type)

{{ entry.title }}

After all this you'll have special "tags" in your cached content that you can run some replacement on, like this:

{{ navigation|replace({('data-url="' ~ craft.request.getUrl() ~ '"'): 'class="active"'})|replace({('data-class-' ~ craft.request.segment(1)): 'active'})|raw }}

You can run two |replace filters after each other, you could just split them up into two steps. Also, this code is untested - I just wrote it from my head so please be aware there might be some typos etc..


How to display Craft Commerce subscription description from a linked entry

I found the answer by viewing the source code in CP. To display the content of the related entry:

{{ plan.information.<fieldHandleInTheRelatedEntry> }}


lineItem.purchasable.title is the variant title, lineItem.purchasable.product.title is the product title.


Craft Commerce - More detailed reporting

Select the date range of your orders:

Then export the line items to csv and open in excel:

You can then use excel to create sums/grouping and charts etc.


Probably and yes.

Using tags for cities:

If you want to allow users to add any city they want, tags are perfect. If not, you should predefine them, and use categories, dropdowns or multi-selects.

Since you don't know if the user has actually entered a city, you should consider validating it with a custom plugin:

Wait for the entries.onBeforeSaveEntry event
Check if the entered tag is a city. (You could use the Google Geocoding API)

.

List entries which have a specific tag:

You can use relations to find all entries which have a specific tag:

{% set tag = craft.tags.name('miami') %}
{% set relatedEntries = craft.entries.section('events').relatedTo(tag) %}

{# Gets all entries which have the 'miami' tag #}


Order PDF in back-end error with Globals

Since the templates are rendered on the server and not in a regular http request (in the front end templates), the globals are not loaded automatically, into the global twig namespace.

You can still access your global set and use it as you usually would by setting it to a variable. You can do so like this:

{% set companyInfo = craft.globals.getSetByHandle('companyInfo') %}

You can then do:

{{ companyInfo.fieldNameHere }}


Migrating categories from Entry to Asset

I would probably do this in two steps:

Create a twig file formatted as a CSV that outputs the category and asset id's, i.e.

AssetId, Category

{% for entry in entries %}
{{ entry.asset.one().id }}, {% for category in categories %}{{ category.id }}{% if not loop.last %}-|-{% endif %}{% endfor %}

{% endfor %}

Use feed me to re-import the categories onto the assets using the CSV.


Try using this.

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

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


Default Formatting Templates don't add "required" to input tag

By default it doesn't add them. You can get that added automatically by adding useRequiredAttribute: true to your form embed tag: https://docs.solspace.com/craft/freeform/v3/template-objects/field.html#properties


How would I list assets from a specific subfolder?

You could use the folderId-parameter in craft.assets:

{% for image in craft.assets.folderId(1) %}

{% endfor %}

You can get the folderId by inspecting the folder-name in the CP.


How can I populate a dropdown via table field type using the default values?

You will only get the defaults for new entries.


How to structure data: Solo Events (Lectures) and Group of Events (Conferences)

My approach:

Create one channel for events with different entry types (solo-events, conference-events)
Create one channel for conferences
Re-use the date fields in both channels
That way you can fetch and order events by the re-used date fields from both channels limiting to the entry types of solo-events and conferences with one query. That makes listings, filtering and paging easy.
Conference-events can be eager-loaded with the query as well
The entry type for conference-events has a mandatory entry field for the conference
In the control panel you can show the related conference by adding the field as a column in the overview
Speakers is another channel or structure being linked from within the conference-events

Why I would not use:

Matrix: can be easily queried but can not eager load the entry it belongs to
Category: feels wrong to always add categories for new conferences
Structures for events: Structure are not 100% user friendly when adding new entries, as they always need to be sorted manually (though there are some improvements in 3.7 coming up)


You can use {% js %} Twig tag.
It is essential to using JS in Twig. It takes JS code passed to it and appends it at end of the template, right before ending body tag. Multiple js tags can be used - content from each of them will be concated with the rest. You don't need to wrap code passed to {% js %} into <script> tags - js will do that for you.
{% js %}
    console.log('Hello World');
    /* you can add your js code here */
{% endjs %}


Get locale entry.title in other languages

You can use the 'locale' and 'id' attributes in your query to request the same entry in another locale.

{{ entry.title }}<br>
{{ craft.entries.id([entry.id]).locale('nl_nl').first.title }}

Update. If there is any chance that the entry/section is disabled for that locale you can also check it first, like so.

{% set nlEntry = craft.entries.id([entry.id]).locale('nl_nl').first %}
{% if nlEntry %}
    {{ nlEntry.title }}
{% endif %}


Handling Endless Recursion in saveEntry?

I'm not sure if it's any less dirty, but another way you could do it would be:

public function init()
{
    craft()->on('entries.saveEntry', function(Event $event)
    {
        $entry = $event->params['entry'];

        if ($entry->section->name == "Classes")
        {
            craft()->db->createCommand()->update(
                'entries',
                array('expiryDate' => DateTimeHelper::formatTimeForDb($entry->classDate)),
                array('id' => $entry->id)
            );
        }
    });
}


Ajax Function on a search form not working in Safari & IE

Try attaching the listener on the forms submit event instead, and prevent that instead of just the click on the button. Something like this (make sure you change the selector for your form):

{% if not craft.request.isAjax %}
    {% set pagingJs %}
        $(function () {
            $('#myForm').on('submit', function (e) {
                e.preventDefault();

                $( ".searchResult" ).remove();
                $( ".noResult" ).remove();

                var search = $('#searchField').val();

                $('#loading').show();
                $.get( "/?q="+search, function( data ) {
                    data = $('#searchQuery', data).html();
                    $( "#searchQuery" ).append(data);
                });
            });
        });
        $( document ).ajaxStop(function() {
           $('#loading').hide();
        });
    {% endset %}
{% includeJs pagingJs %}
{% endif %}


From searching the files (i.e. 'craft/app/Craft.php' line 124) it looks like you can get it using:

craft()->getSiteName()


Craft will inject the current entry by default in your template. All you have to do is to remove this loop

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

And you are fine.

Currently you are fetching all entries within your section. If you don't want to display them all but only the current you should not do that


Returning an array to Twig from a plugin

Your plugin should be able to handle PHP arrays just fine.

craft/plugins/myplugin/variables/MyPluginVariable.php

function getArray()
{
    return array('hi', 'there');
}

craft/templates/template.twig

{% set result = craft.myPlugin.getArray() %}
{% for item in result %}
    {{ item }}
{% endfor %}

The error you're seeing is likely because output itself is an array. If you have devMode enabled you can try a {{ dump(output) }} inside your for-loop to see what it actually is / contains.


Allow user to change or delete their photo for their profile from the front end

Before you can allow a user to manage their profile photo in your front-end profile edit form, be sure to update your form tag with the enctype="multipart/form-data" parameter:

<form method="post" enctype="multipart/form-data">

You can access a users profile photo using the currentUser global and fallback to a different image like so:

{% if currentUser.photoUrl %}

{% else %}

{% endif %}

The upload and manage part becomes a bit trickier.  Setting up a basic use case is fairly straightforward but if you want to begin giving the user a better UI and more feedback as to the status of the uploaded image, you'll have to get into some css and javascript.

For example, when you delete a photo you might want to swap in the fallback image.  When an image is uploaded, you may want to display the image instead of just the filename for the user. Before a user has uploaded an image, you probably don't want to display the delete button.

I'm not going to go into those items here, but here's one approach to get you started with the functionality:

{# Check to see if the user has a photo  #}
{% if currentUser.photoUrl %}

    {# If a photo exists, give the option to change the user photo #}
    <input type="file" name="userPhoto" value="Change Photo">

{% else %}

    {# If no photo exists, give the option to upload a new one #}
    <input type="file" name="userPhoto" value="Upload">

{% endif %}

If you want to be more brief, you can do the same using a ternary operator:

<input type="file" name="userPhoto" value="{{ (currentUser.photoUrl ? 'Change Photo' : 'Upload') }}">

In  both cases, at different points in the process, you may want to give the user an option to remove their photo. To delete a photo, you can pass any value to an input field called deleteUserPhoto.

{# Setup a delete action (see javascript snippet below) #}
Delete

{# Setup a hidden deleteUserPhoto field with no value #}
<input type="hidden" name="deleteUserPhoto" id="deleteUserPhotoInput" value="">

When a user clicks the delete button you want to update the deleteUserPhoto input field to have a value.  Any value works.  Here's an example using jQuery:

(function() {

    // Bind an action to the deleteUserPhotoAction click event
    $("#deleteUserPhotoAction").on('click', function() {

        // Add the value 'zap' to the deleteUserPhoto input
        document.getElementById("deleteUserPhotoInput").value = 'zap';

    });

})();


Best practices of converting an already created site into Craft CMS?

If you're not already on a CMS, I'd recommend migrating to Craft sooner rather than later. Sounds like you're definitely planning on migrating to Craft, so I see no valuable reason to delay.

Pros of migrating now:

Awesome Craft features, like Matrix
Plugins
Twig

Cons of migrating later:

More legacy code to port
More legacy data to restructure

You'll notice that both of those lists reinforce the idea of migrating now. ;)


Records can do that too (where that = hold data), but, according to Craft docs, Records should never ever leave Service layer. So, yes, you do need a model too.


Seems like you want to create a custom Element or you would like to extend the existing Entry Element.
It is all stated in the docs You can see how to create custom actions as well here

Here is stated how to create a custom index page

{% extends '_layouts/elementindex' %}
{% set title = 'Products' %}
{% set elementType = 'ns\\prefix\\elements\\Product' %}

You can then extend the BaseElementIndex in order to change Javascript functionality

Craft.elementIndex = Craft.createElementIndex('{{ elementType|e("js") }}', $('#main'), {
    context:        '{{ context }}',
    storageKey:     'elementindex.{{ elementType }}',
    criteria:       Craft.defaultIndexCriteria
});

You can as well make use of certain events like

Event::on(Elements::class, Elements::EVENT_AFTER_SAVE_ELEMENT, function($event){
    // resave all other elements
});


I ran into two different issues that prevented me from logging into Craft CMS:

1) By default, Craft CMS uses PHP sessions and my PHP installation (via homebrew) had a blank value under "session.save_path". I updated my php.ini file and searched for "session.save_path", it was commented out, so I uncommented it. It now looks like this: session.save_path = "/tmp"

2) The second thing I noticed is that Craft CMS 3 uses the Yii 2 framework, diving into that framework I found a condition that checks a user's IP address. If the IP address is empty, then it rejects the user from logging in. In my case, I was using the built-in PHP local webserver (php -S localhost:8000) so my IP address wasn't being sent along in the requests. To fix this, I changed my setup to use NGINX instead.


When using "createElementSelectorModal()" how do you respect selected locale?

The BaseElementSelectorModal class takes a second parameter settings, which can include a criteria object. This criteria object is used to create an ElementCriteriaModel on the server, which means it can have any property an ElementCriteriaModel can have – including locale:

var currentLocale = Craft.getLocalStorage('BaseElementIndex.locale') || Craft.locale;

var modal = Craft.createElementSelectorModal('Entry', {
    criteria : {
        locale : currentLocale
    }
});


Get discount data from adjustment object

An adjustment will take a snapshot of the source object that contained the rule for its application.

So the following is an array of a discounts attribute if you have a discount adjustment

{{ adjustment.sourceSnapshot }}

You could get the coupon code with

{{ adjustment.sourceSnapshot.code }}


What is the best way to setup Right to Left language locale in Craft?

You can use the locale as per below examples in your _layout.twig file.

<body class="{% if craft.locale == 'ar' %}rtl{% endif %}">

Your css would then be:

.rtl {direction:rtl}

And in your <html> like so:

<!DOCTYPE html>
<html dir="{% if craft.locale == 'ar' %}rtl{% endif %} lang="
{{craft.locale}}">
<head>

https://www.w3.org/International/questions/qa-html-dir