Two domains - single install - Live Preview works only on one

In order to get Live Preview to work across different subdomains on a single install, you'll need to setup a few extra things as outlined in this support article: https://craftcms.com/support/cross-domain-live-preview


How do I update a Craft website without losing data?

You can always add the fields manually to the live site, works best imo if you made a limited amount of changes.

If you have made a lot of changes, a plugin like Firstborn's Migration Manager could do the trick. I have never used it personally, but it seems to do a lot of great things and uses the built-in migration system of Craft 3. Probably worth to give it a spin. There's also a Craft 2 version.


Set Default Entry Types for elements in a Structure Section

I'm not sure if you can set a default entry type within Craft.

But a reasonably workaround would be to go to Settings > Sections, then click 'Edit entry types' for the section you need to apply this to. Next, drag the entry type you would like to be used by default to the top of the entry-type list.

That way, when a new entry is added to the Section, the default entry type will be whichever type is the top of the list.

Hope this helps, but as I say there may be some other answers that offer a cleaner approach.


Using renderTemplate for a plain text twig template

This is isn't an elegant way of doing it, but essentially as per Stephen's suggestion, if you can wrap the plain text output in a pre block, the preview will visually render the spacing and line breaks in HTML mode in the same way it would be received via email.

You could do this in the actionPreview function itself, or alternatively in the template use a condition that would only be true when the email template is being accessed in Craft for this purpose. I chose to use craft.request

{% if craft.request.getLastSegment == 'emailPreviewPlain' %}
    {{ '<pre>' | raw }}
{% endif %}

{# Plain text template content goes here #}

{% if craft.request.getLastSegment == 'emailPreviewPlain' %}
    {{ '</pre>' | raw }}
{% endif %}

This then wraps the entire twig template in pre tags when being previewed in Craft, but otherwise should not render when sent as an email.


You need to include a status(null) to the ElementCriteriaModel to search for disabled entries.

{% set enties = craft.entries.status(null).find() %}

If you have a RelationField you would just add it before you fetch the entries

{% set relatedEntries = entry.myAwesomeField.status(null).find() %}


Looks like overriding the onAfterInstall() method in the main Plugin class is where I should be adding this sort of stuff. Amazing what you find when you actually read the instructions!

More details here


striptags but leave link test in between

Actually, excluding certain tags from being removed is built into the striptags filter.

You can use it like this:

{{ articleTextTrim | striptags('<a>') }}


Is it possible to show a successful logout message?

It is not possible yet, but a quick plugin would make this possible. It would just be a controller with a logout action. You'd be able to call the action as a url with:

/actions/[PluginHandle]/[ControllerName]/[ActionName]

Then you can logout the user the same way Craft does in their controller and edit the redirect as you see fit. Something like this:

craft()->userSession->logout(false);
$this->redirect('?status=logout');

This would log them out and then send them to the homepage with a query attached to the end.


You're looking for the dateUpdated property.

{{ entry.dateUpdated }}


I'd say you want to look at the relations https://craftcms.com/docs/relations#the-relatedTo-param

You would then use craft.entries.section( 'sectionHandle' ).relatedTo( category ) to grab all entries related to the category you are viewing.


Variable 'foo' does not exist in template

Well, oddly, the answer was instead of {{ heading }} i needed to do {{ entry.heading }}

Very odd.


How do I change the URL used to access Craft?

The cpTrigger config setting is what you're looking for.


How can I loop through my entries to export them using Beam?

This is what I ended up doing... obviously remove anything that is specific to your project. But this essentially will export all fields and entries from a passed in sectionHandle as a URL Param.

{# @var craft \craft\web\twig\variables\CraftVariable #}
{# @var section \craft\models\Section #}
{% requireLogin %}
{% spaceless %}

    {# Set the section from the optional sectionHandle param, defaulting to 'answers' #}
    {% set section = 'answers' %}
    {% set sectionHandle = craft.app.request.getParam('sectionHandle') %}
    {% if sectionHandle | length %}
        {% set section = sectionHandle %}
    {% endif %}

    {# Get all of the fields from the layout for the CSV header #}
    {% set csvHeader = [] %}
    {% set fields = craft.sections.sectionByHandle(section).getEntryTypes()[0].getFieldLayout().getFields() %}
    {% for field in fields %}
        {% set csvHeader = csvHeader | merge([field.name]) %}
    {% endfor %}

    {# Get all of the entry content for the CSV data #}
    {% set csvData = [] %}
    {% set entries = craft.entries.section(section).all() %}
    {% for entry in entries %}
        {% set csvRow = [] %}
        {% for field in fields %}
            {% set csvRow = csvRow | merge([entry[field.handle]]) %}
        {% endfor %}
        {% set csvData = csvData | merge([csvRow]) %}
    {% endfor %}

    {# Output the data as a CSV file #}
    {% set options = {
        header: csvHeader,
        rows: csvData
    } %}
    {{ craft.beam.csv(options) }}
{% endspaceless %}

...enjoy. This is what was used (with a few additions) in the project: Post-Mortem: LinkedIn Talent Intelligence Experience


Multi-page form with Yii in a Craft site?

I wouldn't worry going so far outside of Craft and using Yii's forms.

Sounds like all you need is a Craft plugin.  Use normal HTML <form>s from  your template and have them post to your plugin's Controller.  Each step in the form can be another action on the controller.  You can persist data between form steps by saving to Craft's HttpSessionService, which is just a thin wrapper for PHP's global $_SESSION variable.

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

and:

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


Sprout Email Plugin and Multilanguage. How to translate SubjectLine?

First, we'll be adding native support for localization in Craft 3. This is a bit trickier in Craft 2 right now.

Two thoughts. You could set up 3 different emails (each managed in a different language) to be triggered off the same event. Not ideal, but an option.

Aside from that, Sprout Email does run the subjectLine field through renderObjectTemplate so you could use a field in whatever is triggering your event as a dynamic variable for the Subject Line.


Craft 3 Plugin Development: Add CSS and JS File to Frontend Templates

Did you place the init function within your asset bundle class as stated in the docs?

e.g.:

<?php
namespace ns\prefix;

use craft\web\AssetBundle;
use craft\web\assets\cp\CpAsset;

class MyPluginAsset extends AssetBundle
{
    public function init()
    {
        // define the path that your publishable resources live
        $this->sourcePath = '@ns/prefix/resources';

        // define the dependencies
        $this->depends = [
            CpAsset::class,
        ];

        // define the relative path to CSS/JS files that should be registered with the page
        // when this asset bundle is registered
        $this->js = [
            'script.js',
        ];

        $this->css = [
            'styles.css',
        ];

        parent::init();
    }
}

If so, there is only one step left to register the asset in your template (e.g. yourplugin/src/templates/index.twig), you simply have to register it in your template with:

{% do view.registerAssetBundle("ns\\prefix\\FooBundle") %}

If it still does't work, you could generate a minimalistic plugin scaffolding with https://pluginfactory.io/ , its all set up for you and commented out.

Update:
To register the plugins assetbundle in your frontend layout, add

<body>
  {{ beginBody() }
    .
    .
    .
    content
    .
    .
    .
    {% do view.registerAssetBundle("ns\\prefix\\FooBundle") %}
  {{ endBody() }}
</body>

to your frontend templates, e.g. in your main layout.twig at the start and the end of the body tag.


Where can I find someone to help build my Craft website?

UPDATE

As of July 2016, there is now a new jobs board dedicated exclusively to Craft CMS!

  Work With Craft

* Disclaimer: I run the WWC site.

ORIGINAL

There are a few great resources out there for finding Craft developers... Any of these methods should help you track down someone to help you with your website:

Post on the Jobs board at Straight Up Craft
Mention it on Craft Discord, specifically the #jobs channel
Tweet about it on Twitter, using the #craftcms hash tag

To be clear, you won't find anyone here on Stack Exchange. This is typically a resource for developers trying to resolve their programming and architecture issues.

Good luck! :)


You could use Craft::$app->getRequest()->getIsCpRequest() (docs) and do something like this in your innit:

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

    if (!Craft::$app->getRequest()->getIsCpRequest()) {
        // Listens for EVENT_AFTER_SAVE_ELEMENT and element instanceof Entry
        self::newEntryElementIsSaved();
    }
}

Then further down add:

protected function newEntryElementIsSaved()
{
    Event::on(
        Elements::class,
        Elements::EVENT_AFTER_SAVE_ELEMENT,
        function (ElementEvent $event){
            // Get the correct Entry that's currently saving
            if ($event->element instanceof craft\elements\Entry) {
                $entry = $event->element;
                // Set $field to the Field Value
                $field =  $entry->getFieldValue('proposalStatus');
                // Set the Proposals > Campaign Authors Email
                $owner =  $entry->getFieldValue('proposalCampaign')->first()->getAuthor()->emailAddress;

                if($field == 'delivered') {
                  return Craft::$app
                      ->getMailer()
                      ->compose()
                      ->setFrom('test@test.com')
                      ->setTo($owner)
                      ->setSubject('Proposal Delivered!')
                      ->send();
                }
            }
        } // Close Function
    ); // Close Event
}


Can I add a custom canonical URL to a page if also using SEOmatic?

Robin's answer above is valid, but I have managed to create an override in my main _layout template like this:

{% if entry.canonicalUrl|length > 0 %}
    {% set seomaticMeta = seomaticMeta | merge({'canonicalUrl': entry.canonicalUrl}) %}
{% endif %}

{% hook 'seomaticRender' %}


Where and how should you listen for entry delete in plugin?

You can add something like this to your plugin's init() method:

craft()->on('entries.onDeleteEntry', function(Event $event) {
    // Do your custom logic here.
    // Note that you can access the entry that was just deleted via $event->params['entry']
});

Or, better yet, from your custom table, make sure the foreign key that you've created on your entryId column back to the entries table has a CASCADE DELETE setup on it so that when Craft deletes the entry, it will cascade down and delete it from your table as well.


In Craft Commerce, is it possible to show a more meaningful error when the customer tries to add more of a product than is in stock to the cart

If you want to modify the error message, the way to do is not to use the craft.app.session.getFlash('error') value but use the cart.errors instead. Each of the errors has a unique key for specific error then you can add a condition on what message to display. It would something this.
{% if cart.errors|length %}

            {% for attribute, errors in cart.errors %}
               {% if attribute == "lineItems.0.qty" %}
                    {% for key, error in errors %}

Product is not available

                    {% endfor %}
                {% else %}
                    {% for key, error in errors %}

{{ attribute }}: {{ error }}

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

{% endif %}

You could also modify the Unable to cart message by adding this to the update cart form
E.g.
{{ hiddenInput('failMessage', 'Error adding cart.'|hash) }}


Duplicate an existing Order as a new Cart in Commerce

Using the MultiAdd plugin, you can do the following on the order page:

<form method="POST">
    <input type="hidden" name="action" value="multiAdd/multiAdd">
    <input type="hidden" name="redirect" value="commerce/cart">
    {{ getCsrfInput() }}
    {% for item in order.lineItems %}
        {% set itemNumber = loop.index %}
        <input type="hidden" name="items[{{ itemNumber }}][qty]" value="{{ item.qty }}">
        <input type="hidden" name="items[{{ itemNumber }}][note]" value="{{ item.note }}">
        <input type="hidden" name="items[{{ itemNumber }}][purchasableId]" value="{{ item.purchasableId }}">
        {% for key, option in item.options %}
            <input type="hidden" name="items[{{ itemNumber }}][options][{{ key }}]" value="{{ option }}">
        {% endfor %}
    {% endfor %}
    <input type="submit" value="Order Again" />
</form>

This adds a "Order Again" button with the same products and quantities, but options may be bit more difficult to sort out.


"Template Not Found" error when trying to access a module controller action

You'll either need to use the action url http://localhost/actions/my-module/scrape/push since only those will route to controllers by default or create a custom route to your controller


Ordering entries based on an eager-loaded element's custom field

This requires a bit of extra work on the ElementQuery, but it can be done in the same query.

We need to perform an inner join on the relation between the movie and the show and then another inner join on the show's content table. Finally we can order on the custom field of the show's content table.

{% set currentMovies = craft.entries()
    .section('movies')
    .type('movie')
    .limit(null)
    .with([
        'shows',
        'poster',
        'stills'
    ])
    .innerJoin('{{%relations}} shows_relation', '[[shows_relation.sourceId]] = [[elements.id]]')
    .innerJoin('{{%content}} shows_content', '[[shows_content.elementId]] = [[shows_relation.targetId]]')
    .orderBy('shows_content.field_startingDate asc')
%}


Show entries in the Control Panel as a grid, to reorder position

In the Craft backend, I don't think this is possible without (creating) a plugin or module of sorts. Even then, I don't think the element index page is extendable enough to accomplish what you want to accomplish.

Even if you were able to get this done, one way or another, how would you take into account a responsive situation, where more or less than 5 image squares are shown for larger or smaller screens? Would the CP mimic this behaviour?

The only thing I can think of is some sort of table field (Super Table, maybe?), in which you have 5 columns and any number of rows, and every column contains one asset field.


Each user account gets their own "temporary uploads" folder that by default will be a subfolder under storage/runtime/assets/tempuploads.

There are several places there this is used in Craft... one example is if an Asset field has its "Upload Location" set to something dynamic based on the value of another field.  When saving a new element, Craft won't know the value of that upload location until after the element is actually saved, so it keeps the uploaded file for the Asset field in the "temporary uploads" folder, then moves it out of there after the element has been successfully saved.

  Can I disable/hide it?

You can't disable it natively, but you'd probably be able to use some CSS to hide it if you really wanted: https://github.com/doublesecretagency/craft-cpcss


Craft Commerce 1.2.1238 added support for the REST based Multi-Safepay gateway.


Create custom field to input canonical url in a page

If you truly want to this via a custom field:

Admin > Settings > Fields is where you create custom fields.
Settings > Sections > Edit Entry Type is where you assign custom fields to your section. You drag and drop the field under "Design Your Field Layout".
You can then output the custom field in your template using {{ entry.customFieldHandle }} for example.

A more common approach would be to code this tag in your templates instead of using a custom field. I can't give you a very specific approach to try with the code since I do not know your site structure and desired result.


In short, you need to set the selected attribute on the option element based on the sort order.

So, if the sort order is title asc, then that option would have the selected (selected="selected") attribute set on it.

I took the liberty to refactor your code to render sort options dynamically and make the selected sort order sticky by comparing the current option being iterated over, against the selected sort option.

{% set sortOptions = [
    {
        label: 'New - Old',
        value: 'postDate asc'
    },
    {
        label: 'Name Z - A',
        value: 'title desc'
    },
    {
        label: 'Name A - Z',
        value: 'title asc'
    },
] %}

{% set selectedSortOption = craft.request.getParam('order', 'title asc') %}

{% for category in craft.categories.group('university').order(selectedSortOption) %}
    {{ category.title }}
{% endfor %}

<select class="sort-web w-select" data-name="Sort" id="sortQuery" name="Sort">
    {% for sortOption in sortOptions %}
        <option value="{{ sortOption.value }}" {{ sortOption.value == selectedSortOption ? 'selected' }}>
            {{ sortOption.label }}
        </option>
    {% endfor %}
</select>

Feel free to follow up if you have any questions.


What are the yaml files in config/project? Should I commit them?

Those are your Project Config files.
You'll definitely want to 1) read up on it so you're using it properly and 2) commit those files to your repo. :)


How do you add support to manage content in multiple languages in a plugin with a custom Element Type?

It all starts in Your ElementType where you need to return true on the isLocalized function (Line 62 in BaseElementType.php).

Setting this to true will tell Craft that data is stored per-locale, and it's local choices are based on your Element Model's getLocales function. You can get a basic example from Line 231 of BaseElementModel.php.

Craft's Entry Element actually allows you to choose which locale's are used on a per section basis. You can see an Entry gather its locales on Line 54 in EntryModel.php and Line 57 in SectionModel.php. A section stores its locale options in a related table via SectionLocaleRecord.

The rest should be handled by Craft so long as you set localeEnabled to true and locale to a locale ID in your model before passing it along to saveElement.

The rest of the work is templating, which you can reference how P&T do it in templates/entries/_edit.html.


How can I get spaces to render in my dropdown option label template call?

It turns out this was happening because i'd set some values for my content and then changed the structure of the field. I just reset the values for my content and all was well.


The Order History is the history of that particular order and not designed to pull in other prior orders from that customer.

You might want to make a feature request if you want to be able to see customer histories in the order view:
https://github.com/craftcms/commerce/issues

....if they're a registered Craft user you can use the email at the top to get to their profile (and thus to that field) of course, but that doesn't not help for guest users.


How to submit custom fields that are added in the right pane to your plugin?

I think I found the answer, correct me if I'm wrong but you can access your post data in your plugin with:

craft()->request->getPost('fields')

Not sure if this is the recommended way.


Found this while searching for a solution. I fixed it by moving this line to the top of the vhost file:

    fastcgi_ignore_headers X-Accel-Expires Expires Cache-Control;

After this all my requests are properly cached and my site loads really fast! My entire vhost file:

fastcgi_cache_path /etc/nginx-cache levels=1:2 keys_zone=phpcache:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_ignore_headers X-Accel-Expires Expires Cache-Control;

server {
        listen   80;
        charset utf8;
        root /home/user/htdocs/public;
        index index.php;
        server_name domain.com;

        set $no_cache 0;

        # Don't cache the CMS admin area
        location /admin {
                set $no_cache 1;
        }

        gzip            on;
        gzip_min_length 10;
        gzip_proxied    expired no-cache no-store private auth;
        gzip_types      text/plain application/xml application/x-javascript text/css image/svg+xml;
        gzip_vary on;

        location ~ \.php$ {
                include fastcgi_params;
                fastcgi_pass unix:/var/run/domain-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

                fastcgi_cache phpcache; # The name of the cache key-zone to use
                fastcgi_cache_valid 200 30m; # What to cache: 'code 200' responses, for half an hour
                fastcgi_cache_methods GET HEAD; # What to cache: only GET and HEAD requests (ot POST)
                add_header X-Fastcgi-Cache $upstream_cache_status; # Allow us to see if the cache was HIT, MISS, or BYPASSED inside a browser's Inspector panel
                fastcgi_cache_bypass $no_cache; # Dont pull from the cache if true
                fastcgi_no_cache $no_cache; # Dont save to the cache if true
        }

         location ~ ^(.*)$ {
                 try_files $uri $uri/ /index.php?p=$uri&$args;
        }

        location ~* \.(js|css|png|jpg|jpeg|gif|ico|woff|ttf|svg)(\?ver=[0-9.]+)?$ { expires 1w; }

        location ~ /\.ht {
                deny all;
                return 404;
        }
}


Is there a way to compare what has changed on an entry while it's being saved?

You're probably looking for Element::getDirtyAttributes() and Element::getDirtyFields()!
The former is for native class properties/attributes (and is based on an ActiveRecord pattern in Yii, I believe...), and the latter is for Craft's "fields," which may or may not be available, based on what type of Element you're looking at (and what FieldLayout it uses).
You're on the right track! The Element's EVENT_AFTER_SAVE event will fire prior to purging the information with $element->markAsClean().

Note that the EVENT_AFTER_SAVE event emitted by your element is different than the similarly-named EVENT_AFTER_SAVE_ELEMENT event from the Elements service!


That should work fine and I just tested locally with a fresh Craft installation on the latest build and ułatwienia works in the slug for me.

Maybe you've got the limitAutoSlugsToAscii config setting set to true and ł gets changed to l in the slug, but you're still entering ł in the URL?


Can I cache an include for use elsewhere in a template?

You would wrap the code in your include in cache tags and use the keyword globally with it.

{% cache globally for 3 years %}


Personally I would set the category select field outside of the matrix block but that's up to you.
The problem you are running in to at the moment is you are not looping over the matrix field.

{% for entry in craft.entries.section('job') %}
    {% for block in entry.matrixFieldName if block.type == 'job' %}
        {% for category in block.category %}

{{category.title}}

        {% endfor %}
        {{ block.title }}

    {% endfor %}
{% endfor %}

So what we are doing here in the first loop we dive into the jobs section.

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

Once we are inside a job entry we loop over the matrix field containing the "job" block. We only want to display the "job" block (security for when you add more blocks in the future).

{% for block in entry.matrixFieldName if block.type == 'job' %}

Once we get into the matrix field we loop over the selected category field. This way you get access to all the fields inside that category (including the title).

{% for category in block.category %}

Now you have access to all the fields.
All the fields you want to use from the jobs entry you can grab by {{ entry.field }}. All the fields inside the matrix block by {{ block.field }}. And everything inside the category by {{ category.field }}.

OLD ANSWER

Correct me if I get you wrong.

I guess you have a field that connects an entry to a category but what you could try is something like this:

{% for entry in craft.entries.section('jobs') %}
    {% for category in entry.CATEGORYFIELD %}

{{category.title}}

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

{% endfor %}

This is if the order doesn't matter.


How do you return a message if no entries are found?

The for tag has an else clause by which you can render a replacement block if no iteration took place because the sequence was empty.

    {% for user in users %}

{{ user.username|e }}

    {% else %}

no user found

    {% endfor %}

reference: http://twig.sensiolabs.org/doc/tags/for.html#the-else-clause


Best way to deal with Impossible to access an attribute ("isEditable") on a NULL variable ("")

You could combine the first three:

{% if entry is defined and entry and entry.isEditable %}

If the first or second part of this logic fails, it will not check the third part so no error will be thrown. The second part is for the rare cases that a variable with the name entry exists but is null.

If entry is defined, it's always an entry (or at least it should be), so you don't have to check if isEditable is defined.


How to create plugin pivot table entries?

There isn't an explicit sync command, but Yii does support MANY_MANY relationships through Active Record and will keep the data in the join table up-to-update automatically if you stick purely with Active Record.


How can I order entries by title when each title is numeric?

You can do that using MySQL’s cast() function:

craft.entries.section('mySection').order('cast(title as unsigned)')

Alternatively, you might get better performance if you create an actual Number field called “numberTitle”, attach it to your Entry Type, and set the Entry Type’s title to be dynamically generated using the template “{numberTitle}”. Then you can just order by that field instead:

craft.entries.section('mySection').order('numberTitle')


Update checkbox value through plugin (Craft 3)

You need to set the field value, not the options

$entry->setFieldValue('fieldHandle' [
    'value1', 'value2'
});
Craft::$app->getElements()->saveElement($entry);

If you want to change the values, the easiest method is

$allOptions = $entry->getFieldValue('fieldHandle');
$selected = [];
foreach($allOptions as $option){
    if($option->selected){
         $selected[] = $option->value;
    }
}
// unset a value
unset($selected[1]);
// add another value
$selected[] = 'anotherValue';
$entry->setFieldValue('fieldHandle', $selected);
Craft::$app->getElements()->saveElement($entry);

edit

Another approach - a little bit less code and more general since it's the same for every single field in Craft - but more resource heavy

$field = Craft::$app->getFields()->getFieldByHandle('handle);
$selected = $field->serializeValue($entry->getFieldValue('handle'), $entry);
$selected[] = 'anotherValue';
$entry->setFieldValue('handle', $selected);
Craft::$app->getElements()->saveElement($entry);


ERROR: relation "assetindexdata_id_seq" already exists on new database

Not sure how the database backup was created and what's being used to restore it, but using this would fix the error:

CREATE SEQUENCE IF NOT EXISTS 'public.assetindexdata_id_seq'

Alternatively, if you delete the database to destroy all of the associated metadata, then it shouldn't matter.

https://www.postgresql.org/docs/9.5/sql-createsequence.html


When adding a new Entry, I'm having an error

Just based on your screenshot, my guess is the settings for your entry type for your "Jobs" section has "Show the Title field" unchecked and you've set the "Title Format" setting to be "jobs".

I'm not sure if you unchecked that box on purpose, but if you re-check it, you can manually set the Title (which the slug is auto-generated from on new entries) on a per-entry basis.


Like Douglas suggested, you may not have the JS file you need so make sure you download the latest build and upload the files.


I don't think that either the single's uri or the handle is technically considered a slug per se, although in the case of singles craft likely interprets the handle as such. A more appropriate way to access a single would be by using its section handle.

(updated)

{% if craft.request.getSegment(1) == "this-is-a-segment" %}
    {% set item = craft.entries.section('mySectionHandle').first() %}
{% endif %}


How do I properly access plugin controllers from the front-end?

Rather than submitting the form, try hitting it with the Craft JS object. Per the docs:

var data = {
    // ...
};

Craft.postActionRequest('cocktailRecipes/ingredients/saveIngredient', data, function(response) {
    // ...
});

https://craftcms.com/docs/plugins/controllers#posting-to-controller-actions-with-javaScript


I'm pretty sure 'default'=>[] isn't doing anything so it's probably not necessary.

If you wanted to force a single attribute to be of a specific model, you could use:

'courierShippingItems'  => array('type' => AttributeType::Mixed, 'model' => 'Shipper_ShippingItemModel');

Regardless, you'll want to use BaseModel's setAttribute to do what you're trying to do and build your entire array up first before assigning it to the attribute.  Something like this:

$shippingItems[] = Shipper_ShippingItemModel::populateModel($data);

$results->setAttribute('courierShippingItems', $shippingItems);


Using Craft Prune - convert JSON Array of Objects to simple array

Ended up working out a solution:

var myData = {{ craft.entries.section('sectionName').find() | prune(['title']) | json_encode() | raw  }};
    var myArray = $.makeArray(myData);
    var newArray = new Array();
    $.each( arr, function(key, value) {
        $.each(value, function(keyNew, valueNew){
            newArray.push(valueNew);
        });
    });


Multiple category output in auto generated entry title

I think you could also use Twig's join filter instead of the for loop:

{{ object.category | join('/') }}


ElementAPI: Error's out if entry doesn't have assets

Why don't you just check if there is at least one photo? Something along the lines of

'transformer' => function(EntryModel $entry) {
    return [
        'ID' => $entry->id,
        'Year' => $entry->year,
        'Manufacturer' => $entry->manufacturer,
        'Model' => $entry->model,
        'Category' => (string)$entry->category[0],
        'Pics' => !empty($entry->listingPhotos) ? $entry->listingPhotos[0]->url : null,
    ];
}


Insert action in front of template, while maintaining entry slug

The easiest way to solve this, would be to use a template hook instead, and put all your PHP code in there.


How to round the decimal value which we store in the admin panel?

Twig offers various filters. So to round the decimal value, we can use a round filter.
The round filter rounds a number to a given precision:
{{ 42.55|round }}
{# outputs 43 #}

{{ 42.55|round(1, 'floor') }}
{# outputs 42.5 #}

The round filter takes two optional arguments; the first one specifies the precision (default is 0) and the second the rounding method (default is common)

common rounds either up or down (rounds the value up to precision
decimal places away from zero, when it is half way there – making 1.5
into 2 and -1.5 into -2).
ceil always rounds up.
floor always rounds down.

For more filter in Craft CMS. You can check below link.
https://craftcms.com/docs/3.x/dev/filters.html


Gatekeeper/Knock Knock Pluging not working

I can't speak for Gatekeeper, but I'm a big fan of Knock Knock.

Were you logged out at the time? If you are logged in, it will bypass the security screen.


Channel URL Format leads to 404s for individual entries

It turned out that when I deleted news/ from the entry URL format, I also deleted it from the entry template path as well because I misunderstood what that field was for (and forgot to revert that change when everything broke).

Thanks to @Brad for drawing my attention to it.


Craft 3: with Base URL of site set up using @web alias, how to display the original URL in Twig templates?

So luckily for us, Brandon recently added the alias() Twig function. It should show up in Craft CMS 3 RC7. You can see the discussion about it here: https://github.com/craftcms/cms/issues/2327


It's currently not a configuration option, but there is a Control-S (Windows) / Command-S (OSX) shortcut that should work on every page in the Control Panel that basically says "save and stay on the same page".


Getting a Matrix field working on the front-end is going to require 2 things:

Setting up the field inputs so the data submits correctly.
Some custom JavaScript to make the blocks repeat and behave how you want them to.

Here's an example of the Matrix input code you'll need on the front-end.  You'll need to update all of the field handle values to fit your situation:

{# You need to include the 'type' input to identify the matrix block type you are submitting. #}
<input type="hidden" name="fields[contact][new1][type]" value="contacts">

{# You should include the 'enabled' input to specify whether the block should be enabled. #}
<input type="hidden" name="fields[contact][new1][enabled]" value="1">

{# All of your custom fields must be within a 'fields' array. #}
<input type="text" name="fields[contact][new1][fields][contactName]">
<input type="text" name="fields[contact][new1][fields][contactEmail]">
<input type="text" name="fields[contact][new1][fields][contactPhone]">

{# For new blocks, you'll want to use the naming convention 'new1', 'new2', 'new3' for each of your blocks. For existing blocks, you can update those values to be the block IDs. #}
<input type="text" name="fields[contact][new2][fields][contactName]">
<input type="text" name="fields[contact][new2][fields][contactEmail]">
<input type="text" name="fields[contact][new2][fields][contactPhone]">

As for the JavaScript, I won't give an example here, but you'll want to create a way for users to create new blocks, update the ID value appropriately using the new1 convention for new entries and the actual IDs for entries that are being edited.


I just noticed that you've posted an answer to your question already.

Your approach using the group filter is probably all you need, as the allDesigns array is sorted by postDate desc and by using the group filter you'll keep that sort order, your author IDs and the nested entries will both be sorted by the design post date.

To query the user models in the order of the IDs passed to the id param, you just need to add the fixedOrder param to your craft.users criteria model.

{# Grab all the Design Entries #}
{% set allDesigns = craft.entries.section('designs').limit(null).find() %}

{# Group by the authorId #}
{% set allDesignsByAuthorId = allDesigns|group('author.id') %}

{# Grab all of the users with the userIds in allDesignsByAuthorId #}
{% set designers = craft.users.group('designers').id(allDesignsByAuthorId|keys).fixedOrder(true) %}


Craft CMS combining element-api and Simple Map plugin

It should work the same way because the modifyElementsQuery should be fired no matter where the ElementQuery object is build so you could insert the same array in your element-api endpoint as you insert in your CraftVariables entries function to  build the EntryQuery since they both use Yiis configure function to build the

'endpoints' => [
    'api/customer-search.json' => [
        'criteria' => [
            'map' => [
                'location' => 'M2 5ND',
                'country' => 'GB',
                'radius' =>  100,
                'unit' => 'mi'
            ],
            'orderBy' => 'distance'
        ],
    ],
]

should theoretically build the same object like

{% set entries = craft.entries.map({
    location: 'M2 5ND',
    country: 'GB',
    radius: 100,
    unit: 'mi'
}).orderBy('distance') %}


Why are my SEOmatic Entry Metas not overriding Sitewide SEO?

If you added the SEO Meta FieldType to existing entries, you'll need to re-save each section in order for it to start pulling content for you. I'm assuming that's what is going on here; see for more details:

https://github.com/nystudio107/seomatic/wiki/05.-SEO-Entry-Meta


How to output siblings including the current entry?

What about doing it like so:

{% set parent = entry.getParent() %}
{% set siblingsPlusMe = parent.getDescendants(1) %}

{% for entry in siblingsPlusMe %}
    <li>{{ entry.link }}</li>
{% endfor %}


You don't need a plugin.  Here's some example code from an old project of mine.

{% spaceless %}

    {% set thisPackage = "" %}

    {% set packageId = craft.request.getSegment(2) %}
    {% if packageId %}
        {% set thisPackage = craft.entries.section('packages').id(packageId).find()[0] %}
    {% endif %}
    {% set craftAdminId = craft.users.admin('1').first().id %}

    {# -- Do some sanity checking, make sure they have perms #}

    {% if thisPackage %}
        {% set authorInfo = craft.users.id(thisPackage.authorId)[0] %}
        {% set thisCurrency = thisPackage.currency.value %}
        {% if authorInfo.id != currentUser.id and craftAdminId != currentUser.id %}
            {% redirect siteUrl %}
        {% endif %}
    {% else %}
            {% redirect siteUrl %}
    {% endif %}

    {% header "Content-Type: text/calendar; charset=utf-8" %}
    {% header "Content-Disposition: attachment; filename=cal.ics" %}
{% endspaceless %}
BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
X-WR-CALNAME:{{ thisPackage.packageTitle | raw | escape }}
PRODID:-//tastystakes/tourneycal//NONSGML v1.0//EN
{% spaceless %}
{% for block in thisPackage.packageTournaments %}
BEGIN:VEVENT
UID:{{ thisPackage.id }}{{ block.id }}{{ authorInfo.email }}
DTSTART:{{ block.date.getTimestamp() | date_modify("+3 hours") | date("Ymd", "UTC") }}T{{ block.date.getTimestamp() | date_modify("+3 hours") | date("Gi", "UTC") }}00Z
DTEND:{{ block.date.getTimestamp() | date_modify("+3 hours") | date_modify("+" ~ block.days ~ " days") | date("Ymd", "UTC") }}T{{ block.date.getTimestamp() | date_modify("+3 hours") | date_modify("+" ~ block.days ~ " days") |date("Gi", "UTC") }}00Z
SUMMARY:{{ block.tourneyName }}
DESCRIPTION:{{ block.tourneyName }}
END:VEVENT
{% endfor %}
END:VCALENDAR
{% endspaceless %}


I need to grab all images from a section and display them in a slide show on the index page.

You'll need to:

Loop through all of your story entries.
Grab the image from each story.
Compile those into a Twig array.
Create your slideshow as needed.

Here's how that all ties together...

{% set storyItems = craft.entries.section('stories').find() %}

{% set previewImages = [] %}

{% for item in storyItems %}
    {% set currentImage = item.slideshowImage.first() %}
    {% set previewImages = previewImages | merge(currentImage) %}
{% endfor %}

{# RENDER YOUR SLIDESHOW FROM previewImages #}

You'll need to initialize the previewImages array before beginning the for loop... Loops in Twig have their own scope.

  The limit and offset are just to make the slider I have work...

I'm not sure exactly what you're trying to do with the offset, but I'd recommend manipulating your images array in Twig (as opposed to fancy queries to target specific images).


Is it possible to group my Craft plugins using the PSR-0 Standard?

Craft plugin naming conventions follow a specific format.

The plugin folder must live immediately under the craft/plugin folder and it must be the all lowercase name of your plugin's handle.

Your primary plugin class must live immediately in that folder and is named after your plugin's handle plus the word "Plugin".  i.e. PluginHandlePlugin.

Craft doesn't support any concept of multiple primary plugin class files in one plugin folder.


Joining in at this point. We have some sites powered by Craft which need to get some updates. Its absolutely acceptable if the dev version is outdated regarding the content. Making content changes should not be our job, and we mostly work with placeholder and testing content anyway.

The whole next procedure is optional, so enabling this behavior with a config param (or auto-enable when using dev-mode) might be the best idea.

Best would be to write structural changes along with non-content-related settings like asset transforms, plugin settings etc into a file called "_migrations.sql".

Before pushing an update from "dev" to "production", you simply need to press a "increment database structure version" button which then renames the file to "migrations-($v+1).sql". Also the version number in the database gets incremented so the saved version number is directly up-to-date with latest migration file version number.

If an update then goes live, the production database will be behind latest migration file version and executes them like the craft migrations do, incrementing the structure version in database too. Database will be fully up-to-date at this point without overwriting or changing any entry or asset.

In combination with git we could put these migration files under version control so they get part of the commit without committing all the other trash that changed in the database while working on it.

As long as this is not possible from Craft itself, a dump must be made before and after changes are made and manually processed to create migration by hand, which also must be manually executed on production environment. Depending on the amount of changes this can be very frustrating and time consuming.

Making the web developers spend less time and struggling on daily problems would cause more time for more projects to be made with craft. A win-win situation on both sides.


Search for the entry Id with the search form

This currently isn't possible with Craft's native search solution.

Element IDs aren't indexed in the craft_searchindex table in the database.

As a workaround you could maybe use the Preparse plugin to copy the entry ID into a custom field called "entryId" so you could search via entryId:####.


Import local image with FeedMe assumes wrong folderId

So, I found the problem / solution myself:

I have 2 file volumes in my Craft installation (documents, images)
The asset field I am trying to fill via FeedMe is in its configuration limited to the "images" file volume, but the default location for uploads is (erroneously) configured in the documents share.
In this case, FeedMe is determining the folderId from the default location for uploads.
The same thing happens, if all volumes are configured for selection, so in my eyes this is a bug, which I filed here (https://github.com/craftcms/feed-me/issues/833)
So after changing the default upload location of my asset field to be where my files are actually located ("images" volume), everything works.
The column value needs to be the filename only, no alias or anything else prepended.


Ah I found it: the option to enter the custom slug is displayed when you uncheck the Title.

And I set

    // don't accept umlauts for slugs
    'limitAutoSlugsToAscii' => true,

in the config.


I too just had this problem - upon any action in the control panel flashed "An unknown error occurred".

What I found in my craft web.log was:
"ErrorException: ignore_user_abort() has been disabled for security reasons in"

Apparently in my server setup via Runcloud there are various advanced boilerplate Disable_Functions. I removed "ignore_user_abort". Problem solved.

Now the question is what does ignore_user_abort actually do...

Craft 3
PHP 7.2


Hide search results depending on field value

Instead of adding the filtering criteria to the search parameter, I would use a custom field parameter for the showInSearch field.

{% set miniCards = craft.entries.search(query).showInSearch('not 1').limit(12) %}


Why aren't dynamic folders being generated for assets?

Problem solved thanks to Craft Twitter support; needed to re-build the Asset Indexes; because I'd added that field after already creating an entry the asset index was stale and needed flushing.

Open Craft admin dashboard
Click Settings
Click Update Asset Indexes
Click Go!

This process scans through the list of assets in the database and ensures it matches what is in the file system and updates the database as needed.


The toolbar is now set to be fixed by default, even if you don't have that setting in your Redactor config file at all (this applies to all Craft installs before version 2.0.2527).

To make it scroll with you page again, edit you config file in craft/config/redactor/[config name].json and set or modify the following property to:

toolbarFixed: false

(This is not a typo! The property name changed from toolbarFixedBox to toolbarFixed with Redactor 10 / Craft 2.3. Craft's default configs will be updated with the next release got updated with today's release. Thanks to Brandon for the support!!)


See this tutorial by Algolia for autocomplete search: https://www.algolia.com/doc/guides/search/auto-complete/

You would use Search Plus only to keep your index in sync with your sections


Craft 2.x includes Guzzle 3 natively, so you could write a Craft plugin that uses it to consume your web service.

There are plenty of examples in the Guzzle 3 docs on how to do that (as well as in Craft itself).

You could also use something like this: https://straightupcraft.com/craft-plugins/guzzle

Which is a wrapper for Craft's Guzzle 3 you can use from a template.


You should be able to handle this with some logic in a plugin listening to events like:

https://craftcommerce.com/docs/events-reference#commerce_cart.onbeforeaddtocart

The parameters for this include both the order as it stands, and the lineItem being added to the cart, which gives you the opportunity to manipulate both.  You could clear the order, and chec the qty of the lineitem being added is 1 at this point (and change it if needed).

Obviously it would be good to have some front end stuff in place limiting the quantity to 1 as well.


Sometimes getting sent to /admin/undefined after login

This happened for me when I had the LastPass browser plugin version 3.3.1. Once I upgraded to 4.1.29, the issue went away.


Using a variable with array of ElementIds to use in craft.entries.id

I'm not sure where you're getting the id's from but you will need to pass an array into craft.entries.id so try:

{% set navsubids = craft.amNav.getNavRaw("hoofdnavigatie", {startFromId:25})  %}

{% set navsubidarray = [] %}

{% for navsubid in navsubids %}
  {% set navsubidarray = navsubidarray|merge([navsubid.elementId]) %}
{% endfor %}

{% for entry in craft.entries.id( navsubidarray ) %}
  {{ entry.title }}<br>
{% endfor %}

When you used {% set navsubidarray = navsubidarray|join(', ') %} you were creating a string of the values in the array.


Try it without the quotes:

{% set transform = {
       mode: block.imageMode,
       width: block.imageWidth,
       position: block.imageFocus
   }
%}


Cannot enable Craft plugin in control panel

My guess is it's a case sensitivity issue with the main plugin class/file name (some operating systems have case sensitive filesystems and some don't).

You can review the requirements for how things should be named here: https://craftcms.com/docs/plugins/setting-things-up

Or better yet, use a site like https://pluginfactory.io/ to generate the boilerplate plugin code for you and compare it to what you have.


Craft 3 js - extend the field layout designer field settings

If someone has a better approach to solve that please tell me because my method right now fells really wrong and like a hack that might be troublesome in the future. I would like to accept the answer of someone else - until then I'll use the following

onKeyDown: function(ev){
    ev.preventDefault();
    var btn = $(ev.target);
    if(btn.data('menubtn')){
        var menu = btn.data('menubtn');
        var options = menu.menu.$menuList;
        if(options.find('.myClass').length === 0){
            options.append('
Another Button wuhu ^.^
')
        }
    }
},
init: function () {
    var e = this;
    var icons = $(".settings.icon");
    $.each(icons, function(index, item){
        var menuBtn = $(item).data('menubtn');
        if(menuBtn){
            var $menu = menuBtn.menu;
            $menu.on('show', $.proxy(e, 'onShowMenu'));
            e.addListener($(item), 'mousedown', 'onKeyDown');
        }
    });
    // add the event listener
    Garnish.$doc.on('click', '.myClass[data-action="myCustomDataAction"]', this.showHoverMenu.bind(this));
},


Ran the Craft Updater from Control Panel the current install is no longer working

Try running
    composer update
Via the command line while in ssh

Or download the latest Craft files and replace your files. Mainly vendor/craftcms it looks like.

Edit:

Update composer.json to this and try running composer update again.

{
  "require": {
    "craftcms/cms": "^3.0.35",
    "vlucas/phpdotenv": "^2.4.0",
    "craftcms/redactor": "^2.1",
    "craftcms/mailgun": "^1.3",
    "craftcms/contact-form": "^2.2",
    "indigoviking/liquid-letters": "^1.2",
    "lukeyouell/craft-contactformtemplates": "1.0.1",
    "doublesecretagency/craft-bootstrap": "4.1.1.2",
    "fatfish/navigation": "1.0.7",
    "superbig/craft3-templateselect": "^2.0",
    "craftcms/ckeditor": "1.0.0-beta.2",
    "verbb/navigation": "^1.0",
    "enupal/slider": "1.2.2",
    "studioespresso/craft-dumper": "^1.3",
    "topshelfcraft/wordsmith": "^3.0"
  },
  "autoload": {
    "psr-4": {
      "modules\\": "modules/"
    }
  },
  "config": {
    "optimize-autoloader": true,
    "platform": {
      "php": "7.0"
    }
  },
  "scripts": {
    "post-root-package-install": [
      "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
    ]
  }
}


How can a user create an entry that is only enabled for 1 locale?

I have tried disabling each locale in the channel settings, but, then the user is required to enable it for their own locale when publishing.

That's the only way to pull off what you're looking for in Craft 2.

With the upcoming Craft 3 refactoring, it would be much easier to pull of with a new event that a plugin could listen to and alter the behavior.

Feel free to make a feature request as well.


Add options to multi-select with Javascript

Your best option would be to create a custom field type. That's quite a bit of work, though.

Failing that, you could add an extra "Other" option to the select field, and create a separate text field to hold the "free form" option.

Caveats

Craft isn't able to automatically validate the association between two fields. In other words, there's no such thing as "if the user selects the 'other' option, then she must also complete the 'Other' field".

If this is a must-have, you could implement some front-end validation, by injecting custom JavaScript into the Control Panel. Once again, a plugin is the best way to go here, but you may also be able to piggy-back on something like craft-cpjs, by Lindsey Diloreto.


I don't know of a solution for footnotes within Rich Text fields aside from the plugin referenced in the comments of the question. As an alternative, consider having a read over Craft Your Content With Markdown And Matrix by Stephen Lewis.  He explains how he handles footnotes using Matrix and smartdown.


You have to use the previous example and format your own code to match.

Instead of

youtube_showinfo="0"

it goes in as

youtube_showinfo:0


Force craft to do another job (queue) and pause the current one

The priority option is for setting the jobs in priority order before they start. A job that is already running will not be interrupted for a more important one.
I would suggest setting up another queue for the longer tasks. That way, your smaller tasks can continue to run separate to the more demanding ones.
There is some guidance on how to do this on an issue here.


Select entries starting with same letter from alphabet list

First, you should create a dynamic route (something like "games/glossary/<slug>") and point it to a template. A dynamic route means you won't have to create a template for every letter. Note the use of the <slug> token, which – although not entirely semantic – should do nicely in this case.

In your template, you'll need to pull the letter from the URL. Note that it's also a good idea to test if the variable is a single character, and in the a-z range (i.e. a valid letter, and not some other entity).

{% set letter = slug is defined and slug|length == 1 and slug matches '/^[a-z]/i' ? slug %}

If there is no valid letter in the slug variable, it's a good idea to throw a 404:

{% if not letter %}
  {% exit 404 %}
{% endif %}

Next, you can actually use search syntax for the title parameter (specifically, a wildcard *), in order to pull all entries with a title starting with the relevant letter:

{% set entries = craft.entries.section('games').title(letter~'*').limit(null).order('title asc') %}

If you want to throw a 404 whenever there aren't any entries for any given letter, it's simply a matter of testing the length property for entries:

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

If you need pagination in your template, it'll work out of the box as usual:

{% paginate craft.entries.section('games').title(letter~'*').limit(10).order('title asc') as pageInfo, pageEntries %}

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

{% for entry in pageEntries %}
    ...


This is possible with Craft Commerce 3 Pro.

Create an email that would trigger on an 'Invoice' order status that you configure. (or any other name you want)

You would make the order in the Control Panel, then mark it as complete (which will set the the default status), then change the status to 'invoice' to trigger the email.

In the email template, link to a front-end payment form with the order number appended as a param like this ?number=78nc4y83fn4830f4nu304 Then in the payment form, pass in the orderNumber param based on the url number param.

This will make payment on the order and mark it as paid.

You can then see all orders with the status of 'invoice' in the CP, and see the ones that are paid or unpaid. You could move the order to a 'completed' status once you verify payment and ship the order.

Hope that helps.


Fields applied to the User area are not translatable?

You're not missing anything; user content is currently not translatable. (It's up to each type of element whether it wants to support translatable content, and we felt that 99% of the time it would not be desirable for users to have translatable profiles.


Force donation purchasable to replace donation of the same amount in cart

Anywhere you have a add donation to cart form, you could check if the donation is in the cart and update it instead:
{% set cart = craft.commerce.carts.cart %}

<form method="post" action="">
    <input type="hidden" name="action" value="commerce/cart/update-cart">
    {{ csrfInput() }}
    {% if cart.lineItems %}
        {% set donation = cart.lineItems|first %} <!-- since we know only the donation is in the cart -->
        <input type="hidden" name="cartUpdatedNotice" value="Donation updated.">
        <input type="hidden" name="lineItems[{{ donation.id }}]" value="{{ donation.id }}">
        <input id="donation-amount" type="text" name="lineItems[{{ donation.id }}][options][donationAmount]"
               value="{{ donation.options.donationAmount }}" placeholder="10">
        <input type="submit" value="Update Donation"/>
    {% else %}
        <input type="hidden" name="cartUpdatedNotice" value="Donation added.">
        <input type="hidden" name="purchasableId" value="{{ craft.commerce.donation.id }}">
        <input id="donation-amount" type="text" name="options[donationAmount]" value="" placeholder="10">
        <input type="submit" value="Add Donation"/>
    {% endif %}
</form>


Filtering entries by multiple categories with multiple filters

Passing the category as a comma delineated string and using craft.request.getParam('category') the second time will not grab the second variable 4rooms.  First you need to parse that string into an array. This will create an array ['forsale','4rooms']. Use the parts of that array to assign to your other variables.

{% set params = craft.request.getParam('category')|split(',') %}
{% set offerCategory = craft.categories.slug(params[0]) %}
{% set offerRooms = craft.categories.slug(params[1]) %}


How do you "pin" a flash error message in the CP?

I have not tried but you could probably use the CP Custom JavaScript plugin to force display of .notification.error as the flash only sets display: none; and does not remove the element.


How can I export or move content from one Craft system into another? (with exactly the same configuration)

This can be a challenging situation. Craft content can be highly relational which makes it tricky to just export and re-import.

Scenario 1: If your database and your clients database were both equivalent before your client added the additional content, you may be able to just migrate over your clients database and replace your own database and get both back in sync.

To migrate the database would involve exporting the database from the clients environment (either via Settings->Tools->Backup Database or via a database admin tool) and reimporting it into your environment with a database admin tool.

Scenario 2: If both you and your client made changes to your respective databases (for example, you both added articles in each environment) and you need to preserve the new articles added in your environment while also migrating over the articles added in the clients environment you have two options.

First, you could just manually re-enter the articles in the right environment. As it sounds like your client added a lot of articles, that might be time consuming, but sometimes these types of mistakes take time to correct manually. It's often the best option.

In the case you added a few articles and your client added many articles, it may make more sense to add your articles to your clients database and then migrate the full database back to your servers as described in Scenario 1.

Your second option would be to migrate the content programmatically. This becomes a bit more technical so you'd probably need to get a front-end or back-end developer involved. And it will only make sense to go this route if the quantity of data you need to migrate is too much to just do manually.

A plugin like Sprout Import can help with this scenario. (Full disclosure, my team developed Sprout Import.) The steps would involve outputting the content from your clients database into a template into an importable JSON format. And then importing the content defined in the JSON file into your database.  The docs and examples within the plugin would go into more detail about the exact format you would need. For this answer, the more general point is that if your data was complex enough, a database migration plugin like Sprout Import could help provide a path toward a solution.


Duplicating Matrix fields with content from another locale

For Matrix fields, you would basically need to duplicate all of this logic (or move it to a separate function), to recreate each Matrix block.

$newBlocks = array();

foreach ($gbr->$fieldHandle->find() as $gbrBlock)
{
    $newBlock = new MatrixBlockModel();
    $newBlock->fieldId = $field->id;
    $newBlock->typeId  = $gbrBlock->getType()->id;
    $newBlock->ownerId = $element->id;
    $newBlock->locale  = $newLocale;

    $newBlockContent = $newBlock->getContent();

    foreach ($gbrBlock->getFieldLayout()->getFields() as $gbrBlockFieldLayoutField)
    {
        // same field value duplication logic...
    }

    $newBlocks[] = $newBlock;
}

$content->$fieldHandle = $newBlocks;

Unfortunately there’s just no easy way to duplicate element content at the moment. Field types each store things differently, and the way they expect their values to be formatted when saving an element may be different from how they are formatted when fetching an existing element from the DB. (This is something we’ve made much easier in Craft 3 though.)


Add your sites in the CMS, under Settings > Sites.
You can setup the Base URL and language per site.


Is it possible to define optional route segments?

You can make a capturing group optional, simply append ? to it. In this case you'd need to add an additional group that includes the backslash and make it optional.

"myplugin(/(?P<myVariable>[-\w]+))?" => array("action" => "myPlugin/myAction")


The template path needs to include your plugin folder name. So in your case the path to your email templates would be pluginname/templates/emails/prospect and the path you pass to render() would be pluginname/emails/prospect.

More info: Plugin template paths explained

But that doesn't explain why the first template path appears to work.

I’d probably keep the templates inside my plugin if they weren’t being used from the front-end. However, if you'd like to change the default template path to your front-end template directory this answer will help.


I am getting this message when creating a new project

That's not an error, but a Composer warning, saying that it can't create its cache folder at /home/cmnd/.composer/cache/repo/https---repo.packagist.org/ (probably because of a permissions issue.
You can ignore it, but Composer will just run slower.


How to create a faceted search/facet filter in Craft Commerce

Algolia is excellent, and I've found the scout plugin to be solid. Algolia will give you pre-built faceted navigation with instantsearch.js so there is very little development time.

Elastic search comes with the added complexity of running/configuring an ES server, will likely require on-going maintenance.

However if you have the time and don't want to rely on 3rd parties, I would recommend just DIY with twig. If you want it to refresh the listing 'live' you can use Sprig, or htmx.
Basically your filters/facets will be a form that passes a query string to your listing page. Your listing page will then check for the query string and filter accordingly.
An example from a recent project:
{# Get any URL Parameters #}

{% set keywords = craft.app.request.getParam('q')|default(null) %}
{% set kind = craft.app.request.getParam('kind')|default('*') %}
{% set order = craft.app.request.getParam('order')|default('title asc') %}

{# Run the query #}

{% set query = entries
  .search(keywords)
  .kind(kind)
  .orderBy(order)
  .limit(30)
%}

The difficulty will be the UI for sliders etc, but there are plenty of libraries for this kind of thing.


Best way to include attachments using EmailService [Craft Plugin]?

In craft/app/models/EmailModel.php the function docblock describes the params:

/**
 * Adds an attachment from a path on the filesystem. Returns false if the file could not be found or accessed.
 *
 * @param string $path Path to the attachment.
 * @param string $name Overrides the attachment name.
 * @param string $encoding File encoding (see $Encoding).
 * @param string $type File extension (MIME) type.
 * @throws phpmailerException
 * @return bool
 */
public function addAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream')
{
    $existingAttachments = $this->attachments;
    $existingAttachments[] = array('path' => $path, 'name' => $name, 'encoding' => $encoding, 'type' => $type);
    $this->attachments = $existingAttachments;
}

Is that what you're looking for?


Displaying An Entry's Image on Edit Page

This is not possible natively, and as far as I know there's currently no plugin to get a such display. You could develop you own plugin with a new custom field type.

However, if you double-click on this Entry you are able to view its fields within the small pop-up window. Maybe that could help if you need a quick preview of its image field.

You could also rethink the way you add your Work Entries: maybe this could be an Assets field instead of an Entries field. Like this, you would be able to display the thumbnail.


You can set an array and order them by random.

{% set gallery = craft.entries.section(['galleryA','galleryB','galleryC']) %}

Then you have to display them by random using .order('RAND()')

So your for loop looks like:

{% for entry in craft.entries.section(gallery).order('RAND()') %}


Craft admin login infinite redirect in cluster

TL/DR

It sounds like you need to enable sticky sessions at your load-balancer/router level, so that the users will be sent back to the same server in the cluster that their session originated on.

The long version

In Craft 2.x, every new user gets new PHP session represented by a file on your web server and a cookie in your browser.  By default PHP names that cookie PHPSESSID, but Craft will default set it to CraftSessionId, although you can configure its name with the phpSessionName config setting.

PHP has a way to use sessions without cookies providing a way to append a unique session ID to the querystring of a URL, but (for many reasons), Craft doesn't support that method.

In addition to the PHP session cookie, Craft will create an identity cookie upon a successful login that has a randomly generated name similar to 4190d8c6874f8615f88325f5b285fc40. That cookie is how Craft keeps track that you're successfully authenticated.

The problem with load-balanced setups that don't use sticky sessions is that with all of these default settings, when a session is started on server A and then a user is bounced to server B, server B has no knowledge of the session because it was created on server A.

There are ways around it, of course, the easiest being to enable stick sessions at the load balancer level, ensuring that users will get sent back to the server their session was started on for the lifetime of that session.

Alternatively, if sticky sessions aren't your thing, you can configured a shared network storage location and tell each web server to use it for its session.save_path, ensuring they all have access to all server-side session files.  If you go this route, you'll also want to set the appId config setting to be identical across all web servers, since it is used in decrypting cookie data (including sessions).  By default it it is randomly generated per Craft installation.


How to display plain text only from redactor without any line break or format

If you're trying to remove HTML tags from the output completely, you can use Twig's striptags filter: https://twig.symfony.com/doc/2.x/filters/striptags.html.

If you want to retain the tags but show the output without any styling, you're going to have to handle that with your CSS by negating any of the existing styling you don't want.


Getting metadata/column names for empty resultset

I was close - I think the problem was the $command->prepare() did not do anything useful, using $command->query() executes the query.

This is working for me

    $sql = "select t.foo, count(o.bar) as amount from craft_table t join craft_otherTable o on t.id = o.id where 1=0 group by t.foo;"
    $command = craft()->db->createCommand($sql);
    $reader = $command->query($parameters);
    $statement = $command->getPdoStatement();
    $result = [];
    $headers = [];
    for($j=0;$j<$statement->columnCount();$j++){
      $headers[] = $statement->getColumnMeta($j)['name'];
    }
    $result['headers'] = $headers;
    $result['rows'] = $reader->readAll();

    // $result['headers'] is now: ['foo', 'amount']
    // $result['rows'] is now: []


You can use either get (via a direct link) or post (via javascript) which can be accessed in your search template using [craft.request.getParam(name)][1], and then either display the template (if a direct link) or return it (via ajax) to your original template.

For a full example using post and ajax see this question or this question. These examples use post and a form, but you could easily adapt this to place your variables in attributes and then retrieve and send those using javascript:

Link

In javascript:

$('.js-triggerhook').on('click', function(e) {
    e.preventDefault();
    var option = $(this).attr('data-option),
        category = $(this).attr('data-category'),
        url = $(this).attr('data-url'),
        data = "option=" + option + "&amp;category=" + category;
    // send post data
    $.post(url, data, function(result) {
        $('#search-results').html(result);
    }, 'html');
})

Or for a direct link using get:

Link

Or for a way to do either on the fly, just by including the class 'js-sendAsAjax':

Link

Then in your javascript:

$('.js-sendAsAjax').on('click', function(e) {
   e.preventDefault();
   var href = $(this).attr('href').split('?'),
       url = href[0],
       data = href[1];
    $.post(url, data, function(result) {
        $('#search-results').html(result);
    });
});


Recovering (or creating a new) admin account

Download and install a fresh copy of Craft from http://buildwithcraft.com somewhere (doesn't matter if it's the same computer your existing site is on or not).
During installation, remember the password you entered when setting up the user.
Open the database and look in the craft_users table. Copy what's in the password column for the user that the installer created over to the password column in the craft_users table for the site you're trying to recover.
If the locked, suspended, pending or archived columns have 1 in them, set them to 0.
If lockoutDate and/or lastInvalidLoginDate have values in them, delete them.
Login to the site you're trying to recover with the password you created in #2.


How to set up Google Tag Manager correctly

Not sure what you want to know: everything you need is in the
Quick Start Guide. Just copy the two pieces in your layout and you are done.

In Craft you are totally free to do everything you want in your frontend templates. The system won't restrict you at all


Covering both "www.domain.com" and "domain.com" in config file settings

What I like to do is explicitly set CRAFT_ENVIRONMENT in my index.php:

switch($_SERVER['SERVER_NAME']) {
  case 'domain.dev':
    define('CRAFT_ENVIRONMENT', 'LOCAL');
    break;
  case 'staging.domain.com':
    define('CRAFT_ENVIRONMENT', 'STAGING');
    break;
  case 'www.domain.com':
  case 'domain.com':
    define('CRAFT_ENVIRONMENT', 'PRODUCTION');
    break;
}

Then in the config file:

return array(
  '*' => array(
    // Settings here
  ),
  'LOCAL' => array(
    // Settings here
  ),
  'STAGING' => array(
    // Settings here
  ),
  'PRODUCTION' => array(
    // Settings here
  )
);

When you set CRAFT_ENVIRONMENT you may want to use the switch default for LOCAL or for PRODUCTION - there are good arguments for going either way.

A separate question is whether you should have people accessing your site at both www.domain.com and domain.com. The answer is most probably no. Pick one, and use .htaccess (on apache) or whatever other method, to redirect either all the www to non-www or the other way around. Otherwise you will have duplicate content, which confuses the search engines (and generally looks unprofessional).


Seems like I needed a bit more configurations for NGINX, something like

location /es/ {
    try_files $uri $uri/ @esrewrites;
}

location @esrewrites {
    rewrite ^/es/(.*)$ /es/index.php?p=$1? last;
}

for each locale.
Source: https://gist.github.com/cmalven/5cc95cce4e495d3a11df

Still not sure if there is a better option that avoids hard coding locales in NGINX config file.


Lots of smart people have tried to solve this problem and it's a tough one to solve, not just in Craft land but WP, and others. And because of Craft's flexible nature, a change in one table usually means many more updates from others.

Arguably the most reliable way I've seen it done is to use a "top-down" approach. Make the content changes in the production data first, then pull them down to staging/dev since production is essentially the "canonical" version.

If you need to make a new field or whatever to keep things current, add it on both sides. Then do your logic part—anything that could cause something to break the front end—on staging.

If you write your own logic for plugins, look into migrations; Craft can handle schema changes pretty well from an old schema to a new one if you write them properly. If you find your developers are doing this a lot, you may need to revisit your content strategy.

Keeping the content in sync is one thing; doing dev work on a rapidly changing schema is tough no matter how you keep things in sync.

Some tools to help with this:

Audit Log
Schematic
Field Manager

This thread has more details on different environments; here's another that talks about some tools I just linked up above.

Would be awesome for P&T to pull a rabbit out of their hat and have some sort of sync across environments as a first party solution, like they did with Commerce. If you want to see something like that, vote for it.


Is it possible to combine information from two blocks from a matrix to an if function?

The question is a little unclear, is this what you are looking for?

{% set requiredProgram = false %}
{% for block in entry.workshopInstructor %}
   {% if block.requiredPrograms.contains('Photoshop')%}
      {% set requiredProgram = true %}
   {% endif %}
{% endfor %}

{% if requiredProgram %}
  Photoshop is enabled on one of this entry's blocks field.
{% endif %}


Using {% cache %} tags around {% template %} includes (or in Header)

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


How to view a draft page in live view without publishing it

This should be possible right out of the box. Make sure that you:

Have the correct entry template set in the Section's settings
Are using Craft's native {{ entry }} variables in the template.

It might be helpful if you posted your template code.


Craft loading SCSS references rather than CSS

The references to .scss files are just to help you find and debug any changes you would like to make - the browsers developer tools are trying to help you by pointing you at the relevant file.

If I 'view source' of your home page I can see that only main.css is loading :)


Is it possible to use environment variables as the cache duration?

The error you're encountering is part of how Pixel & Tonic wrote the cache tag. In short, variables will not work for what you're trying to accomplish. For the longer explanation...

Tags in Twig are made up of tokens. So strings, numbers, variables, functions, tags, and filters are all tokens. When Twig is parsing a tag, it reads all the tokens and checks it against rules in a Twig extension.

The cache tag after seeing a 'for' token will only accept a number as the next token. Not a variable, or a string, or anything else. The bit typed into the template must be a number. For the duration unit, it checks what's there against a list they have already defined. Again, a variable won't work here. Likewise, the 'until' token looks for a date that can be parsed by PHP's strtotime, and 'unless' looks for something that gives it true or false.

You can accomplish the very same thing using built-in config settings. The cacheDuration setting will do as it says using the PHP Interval Specification. If you have a specific cache storage you'd like to use you can use cacheMethod. Setting these will let you use the cache tag without any extra configuration on the tag itself.


Change naming of sections in Craft Commerce CMS

You can do this using a custom translations file for Commerce and override some of the default translation strings.

Go to vendor/commerce/translation/[your-language].php
Review the instances of the word you want to translate (could be a lot)
In your project root, create a directory called translations
Inside of this directory create a directory with your language code (for me it's en).
Inside of the language directory create a file called commerce.php.

In commerce.php start with something like this:

<?php
  return [
     'Products' => 'Projects'
  ];

And keep going until you have all the strings you want translated added.


Why is Craft storing so much temporary files inside the server tmp folder?

Imagick uses the /tmp folder by default, but you can change it: https://github.com/ImageMagick/ImageMagick/issues/399#issuecomment-285793433


As of Smart Map v2.4.2, it is now possible to build more elaborate markers using a nested syntax for the markerOptions value. Try something like this...
{% set options = {
  zoom: 6,
  markerOptions: {
    icon: {
      url: 'https://www.mysite.com/images/map/marker.png',
      scaledSize: 'new google.maps.Size(20,20)'
    }
  }
} %}


How can I translate checkboxes on a frontend user registration form to lightswitch custom fields?

When the checkbox get submitted, it get's transferred with whatever value is set with the value attribute.

Thus, your need to set the value to 1. Your code should be more like this:

<div class="checkbox">
  <label>
    <input type="checkbox" id="memberShowEmailLink" name="fields[memberShowEmailLink]" value="1" {% if account is defined and account.memberShowEmailLink %} checked="checked"{% endif %}>
    Show a link to contact me via email in the member directory?
  </label>
</div>


Find related entries from section entry Matrix entry field

I wasn't able to relate the entries back based on another entry using it in a field. I believe there would be a way to do this if you cycled through all of those relating entries and that field and filtered out the ones that matched to current entry. We ended up using categories instead and relations work much better in there!


How can I use a reference tag with a global set using the handle (not the ID)

Currently, you can't.  Only element IDs will work for the reference part of the reference tag when using a global set.

Only entries get two additional formats for the reference part of the tag.

entry-slug
sectionHandle/entry-slug


Craft 3 plugin - how to update entry with field of Entries type

Ok this was easy.  Tried it at first but didn't work and was successful after another go.  All it needed was a array of Entry IDs.

Working code:

$entry = Entry::find()->id($entryId)->one();
$entry->textField = 20; // works
$entry->entriesField = [$relatedEntryId1, $relatedEntryId2]; // works
Craft::$app->elements->saveElement($entry);


Search going to /index.php?q= instead of results

I was missing the typical '/' within the URL

The correct URL for this path should be:

  {{ url('/search/results') }}


How do you display entries in a specific (custom) order?

Try using a structure. You can reorder them in the CP.

{% for entry in craft.entries.section('your_structure') %}
  {{ entry.title }}
{% endfor %}


Get full file url, avoiding the siteUrl trailing slash

Instead of {{siteUrl}}{{entry.ogImage.first().url}}, try {{entry.ogImage.first().getUrl()}}. getUrl() should return the full image path, including host.


What is the proper way to set `currentSite` in a CP template when managing multi-site stuff in Craft 3?

Maybe this is some kind of broad answer too but when you take a look at your CP requests you'll see: the siteHandle is mostly passed as a variable in nearly every request.

As for the URL routes the last segment is always the siteHandle: By default, the current site will be used in every query but as soon as Craft recognizes a bodyParam siteId/criteria['siteId'] (for example in your baseElementIndex) or in the URL route it uses that site for all ElementQueries.

In your CP there is no such a thing like currentSite (at least it is not really used for important logic) instead the current site is determined like

{% for siteId in groupSiteIds %}
    {% if siteId == entry.siteId %}
        // currentSite = entry.siteId
    {% else %}
        // not the current site
    {% endif %}
{% endif %}

When I started I used the same method to check for a parameter siteId within the bodyParam criteria. My plugin routes are always something like this

$event->rules[] = [
    'pattern' => 'form-builder/elements/<action:>/<id:\d+>/<siteHandle:\w+>',
    'route' => 'form-builder/element/<action>',
    'defaults' => [
        'id' => null,
        'siteHandle' => Craft::$app->getSites()->getPrimarySite()->handle,
        'action'    => 'index'
    ]
];

if no siteHandle is passed I use the Craft::$app->getSites()->getPrimarySite()

craft\controllers\EntriesController

public function actionEditEntry(string $sectionHandle, int $entryId = null, int $draftId = null, int $versionId = null, string $siteHandle = null, Entry $entry = null): Response
if ($siteHandle !== null) {
    $variables['site'] = Craft::$app->getSites()->getSiteByHandle($siteHandle);

    if (!$variables['site']) {
        throw new NotFoundHttpException('Invalid site handle: '.$siteHandle);
    }
}

later on, when there is really nothing at all it just assumes the following

if (empty($variables['site'])) {
    /** @noinspection PhpUnhandledExceptionInspection */
    $variables['site'] = Craft::$app->getSites()->getCurrentSite();

    if (!in_array($variables['site']->id, $variables['siteIds'], false)) {
        $variables['site'] = Craft::$app->getSites()->getSiteById($variables['siteIds'][0]);
    }

    $site = $variables['site'];
}

TL:DR

Craft doesn't use the currentSite that much in the CP, it is determined by the current element.siteId or the siteMenu (in js). As soon as you enter the CP the selected site in the menu will be stored in your Javascript session, when you click on create new entry you'll get routed to the site that is specified in your session. I think it's best to manage it the same way


My issue was that the country wasn't being set properly. Since we're only shipping to the US, I had mistakenly commented out my hidden input for the country field.


How do I set the value of a custom entries order field from a plugin?

I was close. I was correct in assuming my syntax was incorrect for setting the value of an entries field.

Since an entries field is an array of elements, not just a single element, I just needed to set the value of the field as an array instead of a string.

Changing

$cart->setContentFromPost(['entriesFieldHandle' => $entry->id]);

to

$cart->setContentFromPost(['entriesFieldHandle' => [$entry->id]]);

seemed to do the trick.

To zoom in a little more, the value needs to be set with 'entriesFieldHandle' => [$entry->id] instead of 'entriesFieldHandle' => $entry->id.


You need to be in the correct namespace try

$reader = new \XMLReader();

Like here


The following code can be used in the init method of a custom module.

Event::on(
    View::class,
    View::EVENT_BEFORE_RENDER_PAGE_TEMPLATE,
    function($event) {
        // Check query string for coupon code
        $couponCode = Craft::$app->getRequest()->getQueryParam('coupon', null);

        if ($couponCode) {
            // Check there is a discount that has this coupon code
            $discount = Commerce::getInstance()->getDiscounts()->getDiscountByCode($couponCode);
            if ($discount) {
                $cart = Commerce::getInstance()->getCarts()->getCart();

                $cart->couponCode = $couponCode;
                Craft::$app->getElements()->saveElement($cart, false);
            }
        }

    }
);

Don't forget the following use statements at the top of the file.

use Craft;
use craft\commerce\Plugin as Commerce;
use craft\web\View;
use yii\base\Event;


Is there a way to retrieve the last date of an event using the Solspace calendar plugin?

Do you mean this?

{% set eventOptions = {
    dateRangeStart: targetStartDate,
    dateRangeEnd: targetEndDate,
    limit: 15,
    search: "EndrepeatHandle:On date"
} %}
{% set events = craft.calendar.events(eventOptions) %}


Table fields in Craft just store their data in a JSON blob in the content table. That means you can't really query them like you would other things, you'd have to load in all of the data, and then filter it out as an array.

While you can certainly do this in Twig, it smacks of a bit too much "business logic" in Twig; so at this point I might be considering one of two options:

Refactoring it out to a
plugin
or
module
that will do the heavy lifting behind the scenes
Changing the schema I'm using to store the data in something that
can be queried, such as moving the data into entries or a matrix block or perhaps a
SuperTable

Or if either of these seems like too much work, or you're not storing a whole lot of data in the Table field, then I'd just do it in Twig by looping through all of the rows in the table, and selecting only the ones that meet my criteria.


Bump up the PHP Memory limit and max execution time, then change the 0 in the first failed task to 1.

After that go into craft, click the tasks and hit "try again"


The short answer is, we should probably update that :)

The long answer is:

The homepage is a “Single” section, and originally, Singles couldn’t have dynamic Title fields like Channel and Structure sections; their titles were static, based on the section’s name. So in this case, that Homepage entry’s title was “Homepage”, and the only way to change that would have been to go into the section’s settings and change its name from there. So, back then, if you wanted to give a Single a “Title”-esque field, it had to be a custom one. Which is what that Heading field is – a custom Plain Text field.

As of Craft 2.2, however, Singles can now have dynamic Title fields. So at that point we should have updated the default fields to stop giving that Homepage section a custom Heading field.

Hope that clears things up a bit. I’ll go ahead and make that change for the next release.


Yes, it's possible. It will require two steps:

Create a setting in your plugin for pluginNameOverride
Use that setting in place of the default name of your plugin when loading your plugin

This does not change the name of the URL slug for your plugin in the admin URL and has different behavior in the UI in Craft 2 and Craft 3.

Craft 2

1) Add a new setting following the instructions in the docs: https://docs.craftcms.com/v2/plugins/plugin-settings.html#settings-page

2) Once you have your setting working. You can do this in the getName method of your primary plugin file:

public function getName()
{
    $pluginName = Craft::t('Your plugin name');
    $pluginNameOverride = $this->getSettings()->pluginNameOverride;

    return $pluginNameOverride ? $pluginNameOverride : $pluginName;
}

Note: While this changes the name in the nav, it also changes the name in several other places, such as the list of plugins on the plugin page. If a user changes it to something odd, it may not be obvious to you or someone else debugging that the website has your plugin installed.

Craft 3

1) Add a new setting following the instructions in the docs:
https://docs.craftcms.com/v3/extend/plugin-settings.html

2) Override the parent label value in the getCpNavItem method

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

    // Allow user to override plugin name in sidebar
    if ($this->getSettings()->pluginNameOverride)
    {
        $parent['label'] = $this->getSettings()->pluginNameOverride;
    }

    return array_merge($parent,[
        'subnav' => [
            'sectionName' => [
                'label' => Craft::t('your-plugin', 'Tab Name'),
                'url'   => 'your-plugin/section-name'
            ]
        ]
    ]);
}

Note: This just changes your plugin name in the sidebar URL. Your plugin will continue to use its original name in the settings area.


What is the proper way to set an asset's upload location using the slugs/ structure path of the entry it is selected from?

To include the handle of the slug, and the path within the structure based on the entry uploaded from in the upload location field I've found the following to work:

{section.handle}/{parent.uri}/{slug}

If there are any gotchas on this let me know and I'll edit this answer to include them.


In a template: Is there a way to call the parent's folder name?

Have you tried setting a variable and passing it down into your include?

{% set parentFolder = craft.request.getFirstSegment %}

Then pass parentFolder (or whatever you name it) down? This of course assumes your first segment is the name of your folder tree.


FeedMe - Import to multi language sites, linking entries

You will need to:

Set Entries to propagate across all sites for you chosen section
Import your main language (which will propagate to all your sites)
Using ID's (or else) to match elements, import second language to update previously propagated entries and correct content.

Here's an article explaining the process.


Of course a couple of minutes after posting this I find the answer.

All you need to do is put the email field handle in the reply to email address input like this

{emailAddress}


I believe its because you are not "hashing" the URL. Either use this https://docs.craftcms.com/v3/dev/functions.html#redirectinput-url or as that the link also mentions:

<input type="hidden" name="redirect" value="{{ craft.app.request.absoluteUrl|hash }}">


You have to create the folder where you want to include your plugins by yourself. There are no requirements how you name it. Let's say you want to create the folder plugins in your Craft folder, then you have to include the plugin in your composer.json like this

"require": {
   "php": ">=7.0.0",
   ....
   "namespace/pluginhandle": "your version",
   "secondred/form-builder": "^1.0" (<--- example how it could look like)
},
"repositories": [
{
  "type": "path",
  "url": "plugins/yourPluginFolderName"
},
{
  "type": "path",
  "url": "plugins/form-builder" (<--- example how it could look like)
},
....

Then you'll need access to your server via ssh and do composer update


Updating private repo plugins from admin?

It's not currently possible. The CP update process involves interactions with the Craft web services and the Craft web services don't have any information about the private repository for your site.


Removing the Save button based on some condition

I would try to do this via JS, using https://plugins.craftcms.com/cp-js
If the information, whether you want to show the button or not, is not available in the entry's edit page itself, create a controller within a module and request the information from the controller via AJAX.


Pull random image from entries marked with a certain category

Welcome to the Craft community @bjyama

{# Step one: pick a random service #}
{% set randomService = craft.entries.section('services').relatedTo(left).order('RAND()').first() %}

{# Step two: pick a random image from the above service #}
{% set randomServiceImage = service.homepageImage.order('RAND()').first() %}

{% if randomServiceImage %}
    <img src="{{ randomServiceImage.getUrl('imageTransformName') }}" alt="">
{% endif %}

For more info, have a look here: https://craftcms.com/docs/templating/craft.entries#order

Let us know how you get on :)


How do I output a dropdown's values if I'm on a registration form not tied to an entry?

The not so elegant way to do this is to re-use the field somewhere else, where you do have access to (e.g. a global set). But you probably want to avoid this, right?

What you can do instead is to access the field directly using craft.fields. This function returns the FieldModel of your field, containing all of its properties. The FieldModel property you want is attributes.settings, where you can access your dropdown options like this:

{% set dropdownField = craft.fields.getFieldbyHandle('dropdownFieldHandle') %}

{% for option in dropdownField.settings.options %}
    {{ option.value }}
{% endfor %}


Yes it is you can see here how to check permissions

You can get the current user with

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

Then you can check the same conditions like in the example link. If the conditions are false you can return an empty array instead of your endpoints

if(!$currentUser->isInGroup('groupHandle')) {
    return [];
}

Please make sure to check if the current user is not null


Craft 3.1.7 live preview multi-site only works on home page

Are those the fields on the non-visible entries translatable by site? It's the most common problem, not setting up some of the fields or subfield as translatable by site.


Editing entries on multisite Craft CMS implementation

You need to make sure the field you are trying to change is set to be translatable.
Go to Settings → Fields → Your field → Translation Method and pick the suitable method for your site (see documentation).


Project config is designed to sync the architecture of your site, not the content, so structural changes can be made without affecting the content. Forms are seen as content, like entries, so this would be the expected behaviour.
The suggested workflow would be to create the form on the production site, then pull to local environment to do any front-end work, then push those changes to production.
The nystudio107 craft scripts are pretty useful for syncing databases and assets if needed.


How can I loop through all entries that are enabled in at least one locale (not necessarily my current locale)?

Just add the locale criteria to your entries call and specify the locale(s) you need to query.

{% set items = craft.entries({
    section: 'sectionHandle',
    limit: null,
    locale:"es_us"
}) %}


How to display submission data on a thank you page with sprout forms?

You can grab the last submitted entry on the thank you page. So using the example, you should be able to do lastEntry.id


Linking to Sections: do it or do something different?

I've found what is probably a better solution;

I create a Single section for each Channel/Structure and use that as a directory for that channel/structure. I then loop through all sections and see if they're of the single type, then get the first (and only) entry of that section.

{# Get all Section #}
{% set sections = craft.sections.getAllSections() %}

{# Loop through all single sections #}
{% for singleSection in sections if singleSection.type == 'single' %}

    {# Get the first (and only) entry of that section #}
    {% set singleEntry = craft.entries.sectionId(singleSection.id).first %}

    {# Output #}

        {{ singleSection }}

{% endfor %}

Let me know if you guys have a better way of doing this!


You should be able to set the desired locale by adding .locale('en') to your code.

Like so:

{% set fields = craft.sections.getSectionByHandle('news').getEntryTypes()[0].locale('en').getFieldLayout().getFields() %}

Assuming you've got english defined as en.


If you take a look at the Relations page from the docs. The last example at the bottom of the page shows how you can do a query using AND for multiple criteria.

The example from the page:

  Passing Multiple Relation Criteria

  There might be times when you need to factor multiple types of
  relations into the mix. For example, outputting all of the current
  user’s favorite cocktails that include Gin:

{% set gin = craft.entries.section('ingredients').slug('gin').first() %}

{% set cocktails = craft.entries.section('cocktails').relatedTo('and',
    { sourceElement: currentUser, field: 'favoriteCocktails' },
    { targetElement: gin, field: 'ingredients' }
) %}

  That first argument ('and') specified that all of the relation
  criteria must be matched. You can pass 'or' instead if you want any of
  the relation criteria to match.

Hopefully that'll point you in the right direction.


How to append / prepend into a rich text field

If you want to prepend another paragraph you could to this:

{% set paragraphs = entry.body|split('
') %}
{% for paragraph in paragraphs %}
  {% if loop.index == 1%}

Prepended Custom Text

  {% endif %}
    {{paragraph|raw}}
{% endfor %}

If you want to display a custom string in the first paragraph itself you could do this:

{% set paragraphs = entry.body|split('
') %}
{% for paragraph in paragraphs %}
  {% if loop.index == 1%}
    {% set paragraph = paragraph|replace({'
': '
My custom prepended Text '}) %}
  {% endif %}
    {{paragraph|raw}}
{% endfor %}

This looks a little bit hacky tough there are probably prettier ways to do so.


Display field content inside a matrix from a different locale

You should be able to query a global set in a different site:
{% set englishMatrixTable = craft.globalSets()
    .handle('globalMatrixTable')
    .site('yourEnglishSiteHandle')
    .one() %}

{{ englishMatrixTable.globalPresenceItem }}


Any ideas on how to set/output something if the previous variant in a for loop has a parameter?

Check out the MN Twig Perversion plugin. It adds a break Twig tag, which allows you to escape from a loop once you have the data you need.


Author of the plugin here - @Lindsey is correct - wrapping the color in quotes is the correct syntax. If you test it with this video, it works fine:
https://vimeo.com/130900978

One thing to note - with Vimeo, a video owner can overwrite this option - so if they set it to a specific theme color, you can't change it through this embed parameter. For more info on the Vimeo API, you can see this documentation: https://developer.vimeo.com/player/embedding


You can do this by overriding fromName and fromEmail in the mailer component config based on your site handle (or language).
You would do this in your config/app.php like so:
'components' => [
    'mailer' => function() {
        // Fetch the site the user is on
        $currentSiteLanguage = Craft::$app->getSites()->currentSite->handle;

        // Fetch the stored email settings
        $settings = craft\helpers\App::mailSettings();

        // Define the name and email address based on language. Change `public` to match your own site handle
        $fromName = $currentSiteLanguage == 'public' ? 'From your public site' : 'Default from name';

        $fromEmail = $currentSiteLanguage == 'public' ? 'email@public.site' : 'default@email.address';

        // Apply the name to existing settings
        $settings->fromName = $fromName;

        // Apply the name to existing settings
        $settings->fromEmail = $fromEmail;

        // Create a Mailer component config with these settings
        $config = craft\helpers\App::mailerConfig($settings);

        // Instantiate and return it
        return Craft::createObject($config);
    },
],


ResaveAllElements task generates fatal error after adding locale

I thought the point of tasks and subtasks was to prevent this thing from happening,

No, a task is just another PHP request subject to the same environmental limitations as any other PHP request.  It just so happens that it runs asynchronously in the background.

I assume you don't have access to a php.ini file to increase values?  You can also try via .htaccess.