Not triggering SEOMatic on save element I'm writing a module that loops over lines in a CSV file to save them as entries. For every entry I save with elements->saveElement($element);, SEOMatic will queue a job that regenerates the sitemap for this type of entries. I'm importing more than 1000 lines this way, so there'd be more than 1000 jobs in the queue, all doing the same thing.
Is there a way to disable this hook so it wouldn't get triggered for every entry?

Here's a part of the code right now:

while (($csv = fgetcsv($handle)) !== false) {
    $entry = Entry::find()->siteId($siteId)->section('products')->where(['content.field_productId' => $csv[0]])->one();

    if (!$entry) {
        $entry = new Entry();
        $entry->sectionId = Craft::$app->sections->getSectionByHandle('products')->id;
        $entry->typeId = 1;
        $entry->siteId = $siteId;
    }

    ...
    ...
    ...

    try {
        Craft::$app->elements->saveElement($entry, true, true, false);
    } catch (Throwable $e) {
        throw new RuntimeException($e);
    }
}

try {
    Craft::$app->elements->resaveElements(Entry::find()->siteId($siteId)->section('products'), false, true, true);
} catch (Throwable $e) {
    throw new RuntimeException($e);
}

By setting the regenerateSitemapsAutomatically to false, SEOMatic won't regenerate a sitemap for every entry saved.
At the end of the job, I set it back to true and save the first element inside of the same section.

Changes to the original code:

Seomatic::$settings->regenerateSitemapsAutomatically=false; // Disable it

while (($csv = fgetcsv($handle)) !== false) {
    $entry = Entry::find()->siteId($siteId)->section('products')->where(['content.field_productId' => $csv[0]])->one();

    if (!$entry) {
        $entry = new Entry();
        $entry->sectionId = Craft::$app->sections->getSectionByHandle('products')->id;
        $entry->typeId = 1;
        $entry->siteId = $siteId;
    }

    ...
    ...
    ...

    try {
        Craft::$app->elements->saveElement($entry);
    } catch (Throwable $e) {
        throw new RuntimeException($e);
    }
}

try {
    Seomatic::$settings->regenerateSitemapsAutomatically=true; // Enable it again
    $firstElement = Entry::find()->siteId($siteId)->section('products')->one();
    Craft::$app->elements->saveElement($firstEntry); // Save first entry again
} catch (Throwable $e) {
    throw new RuntimeException($e);
}

Thanks to Oli for the suggestion.


Changing the label on links I'm adding content to a site that has been set up in Craft. However, it's been set up so that in one section, any link created has the label "How this works". It's a bit unwieldy as it means I can't use the actual information I want to send people to as the link for example:
"Spend less money" as the link rather than body text that says "Spend less money" with a link underneath that says "How this works".

Is there any way I can change this behaviour without getting the site designer to change it in template files?

This is highly dependant on how the fields and templates are set up.

You don't say how you are creating the link. Craft makes no assumptions as to how you are going to be entering content. It's entirely down to the developer to set up the fields and templates according to your needs.

Do you have a text field specifically for entering the link? If there is no accompanying field to add a title then it's most likely you will need to add one and then modify the template to output that field in the title attribute of the link.

If you are adding a link within a Rich Text field then you should be able to edit it from within there. Though if this were the case I don't know why you would have a default value being used.

Either way, it should be a very minor task for a developer to fix.


.env.sh in craft-scrips I'm having trouble setting the variables of the env.sh file for craft-sctipts.
I getting an error: File /common/defaults.sh is missing, aborting. when I try to clear the cache using a cronjob pointing to the clear cache script.
My variables are set in the env.sh file, which is in the scripts directory.
LOCAL_ROOT_PATH="/domains/mydomain.ca/"
REMOTE_ROOT_PATH="/domains/mydomain.ca/"
The scripts are in /domains/mydomain.ca/scripts/ directory.
Any thoughts?

The other error Im getting is dirname: command not found.
I was able to solve this issue by just manually setting the DIR variable in the script I needed to use. There is probably a better way....


How to check if number is prime? How do I check if a given number is prime in twig?

Example using build-in functions (sure, not the best ;-) ).

Supposing that number is our number:

{% set result = 0 %}
{% if number / number|round == 1 %}
    {% set result = 1 %}
    {% if number > 3 %}
        {% for i in 2..number-1 if result == 1 %}
            {% if number is divisibleby(i) %}
                {% set result = 2 %}
            {% endif %}
        {% endfor %}
    {% endif %}
{% endif %}

Now, result equals to:

0, if number is not integer
1, if number is prime
2, if number is composite


Can I open one template/route when Craft is offline? I've set Craft offline (System status). Is it possible to "open" one specific URL route so it can be accessed even though the website is offline?

For example the route: /blog/post

You can add a template called 503.html to your /templates folder. Craft will then use that template whenever the system is turned off, due to the HTTP status being set to 503 (service unavailable).

Inside the 503.html template, you can of course include another template (e.g. blog/post).


Assign Category via Guest Entry Form Is is possible to assign a category via a frontend Guest Entry form.

I tried

<input type="hidden" name="fieldHandle" value="SomeExistingCategorySlug">

But that did not work.

Simply put, a Categories field is an array containing category ids, and your form needs to send it that way:

<input type="hidden" name="fields[fieldHandle][]" value="100">

Adding brackets to your field-handle submits the value as an array, and 100 is the id of the category.


TemplatesController error related to webfont! I'm getting a very strange 404 error on my live site:

  Craft\HttpException: template = fonts/BlissBold-webfont.ttf in  /path/to/mydomain/craft/app/controllers/TemplatesController.php:72

I've searched my complete directory and the only reference to BlissBold-webfont.ttf is in a stylesheet.  How on earth is this affecting the TemplatesController?

TemplateController is what all template requests in Craft get routed through.

That error just means that someone/something is trying to load a resource (in your case yoursite.com/fonts/BlissBold-webfont.ttf) and that doesn't exist on your file system and Craft has no idea how to resolve that request, so it issues a 404 Not Found in response.

It's more of an informational thing than anything and not really an error.

In the upcoming Craft 3, 404's get logged in separate files so as not to clutter up the main logs.


Catch file-size errors in Guest Entries Form I have a front-end entry form using the Guest Entries plugin, with a file input for the user to upload a photo. I am also using the jQuery Form plugin for AJAX submission, but the behavior is the same if I disable it.

The form works great with small file sizes, but if the uploaded image is larger than PHP's upload_max_filesize, I get a fatal error: Imagine\Exception\RuntimeException: Unable to open image.

If the uploaded file is larger than PHP's post_max_size, the page simply reloads - no error is registered. I gather that this error can be difficult to catch, so maybe it's impossible to have a more graceful failure in this case.

However, for file sizes between upload_max_filesize and post_max_size, shouldn't there be a way to return that as a proper error in the errors array, instead of dying in a way that is unhelpful to the end user?

What's probably happening on both of your cases is a PHP fatal error, which are notoriously difficult to recover from.

The upcoming Craft 3 (thanks to some clever tricks in Yii 2), however does handle fatal PHP error much better and in situations like yours, you would be receiving the actually underlying fatal error message.


Redirect issue with login and paths I'm gonna probably find another way around this, but I'm still very new to Craft and want to ask if I'm missing something obvious. This is a commerce site that needs a front-end login.

I have an account template folder with some templating that looks like this (it's an extended layout, leaving out unnecessary lines):

{# account/index.html #}
{% block main %}
    {% if craft.session.isLoggedIn %}
        {% include 'account/account.html' %}
    {% else %}
        {% include 'account/login_signup.html' %}
    {% endif %}
{% endblock %}

And an excerpt from my general.php

{# excerpt from my general.php file #}

'loginPath' => 'account',

'postLoginRedirect' => 'account',

When a logged-out user goes to website.com/account the login_signup.html page is spit out and a user can sign in (ignore the sign-up part). If they type in their info correctly, it leads to an ERR_TOO_MANY_REDIRECTS of account redirecting to account. This doesn't make sense to me, as both the login url and the post-login url point at the same path and load the same template, but the template should obviously handle the two situations differently. It should spit out the account.html template if the user is logged in, and if not, the login_signup.html template. These two template files have nothing in them right now, so it's not some other templating mistake.

If I remove either of the two config variables I presented in my general.php file, everything works but the routes I want aren't there.

I want a logged out user to visit account, get a sign in (login_signup.html) form they then use, and get redirected to account and the template will spit out the account.html template.

Edit Basically, if a user is logged in with my general.php having those two configs set to the same path (account), this always results in too many redirects:

{% block main %}
    {% if craft.session.isLoggedIn %}
        I'm logged in!
    {% else %}
        I should log in!
    {% endif %}
{% endblock %}

Yeah... that won't work.

Craft currently uses the URI segments to determine special path like logging in, out, etc.

So when Craft sees account as the first segment in the URI, its going to treat that as a login request and execute what's in UsersController->actionLogin(), which will see that you're already logged in, and will eventually hit this if the user doesn't have CP access permissions:

// Otherwise send them wherever postLoginRedirect tells us
$postLoginRedirect = craft()->config->get('postLoginRedirect');
$returnUrl = UrlHelper::getSiteUrl($postLoginRedirect);

Which, you've got set to account, then it rinses and repeats given you the infinite redirect loop.


Set Order of Entries What is the best way to set a logic order on a channel of entries. I'd like to be able to set the order of each entry (any unset can default to date afterwards).

Would the best way be just a text field and enter a number? Or is there some other structure?

If you explicitly want a Channel of entries, then you should go with a number field. If, however, you'd use a Structure (with 1 level max), you'd be able to drag and drop entries and use that to order 'em.


Hacksaw replacing "&" with "&" I'm using the Hacksaw plugin to truncate text and it does a great job except instead of rendering HTML entities such as "&", it's outputting them as "&amp;". How can I correct this? Putting them in allow="" doesn't work. Do I need to do something to manipulate the text string first before applying the Hacksaw filter? Or is there a Hacksaw option that would correct this?

Edit for more info...

Example of text as it should appear:

Colour & Light; A House Re-crafted, cover & pg.99-108

Example of text output from Hacksaw:

Colour &amp;amp; Light; A House Re-crafted, cover &amp;amp; pg.99-108

Stupidly I hadn't looked at the HTML until now. It looks like the first &amp; is rendering correctly but then there's a second partial entity after it?!

Template code I've tried:

{% set summary = article.newsArticle.type('text').first().text|hacksaw(words='35', append='...') %}

{% set summary = article.newsArticle.type('text').first().text|hacksaw(words='35', append='...')|raw %}

{% set summary = article.newsArticle.type('text').first().text|raw|hacksaw(words='35', append='...') %}

The order of plugin doesn't appear to have any effect. I get same result with all three of these arrangment above, including no Raw plugin at all.

Edit for answer

As per accepted answer below, final working code is:

{% set summary = article.newsArticle.type('text').first().text|htmlEntityDecode|hacksaw(words='35', append='...') %}

The Craft Helpers plugins did the trick.

You could try to fight that ampersand with the htmlEntityDecode filter that is included in my Craft Helpers plugin https://github.com/carlcs/craft-helpers


currentUser global is null. I can't figure out why Does anyone know why currentUser would return null? I'm logged in as an admin.. actually the only user.

I've cleared cache, logged out and back in, etc. I can't seem to get it to work.

I'm trying to set an edit link for an entry like so:

{% if currentUser %}

        Edit

{% endif %}

And also tried this:

{% if entry.isEditable() %}

        Edit

{% endif %}

Neither are working. Any ideas?

Per Brad's request. I am answering my own question.

I figured out that I was logging in via non-www, and accessing the site at www.

So the official answer is to choose either www or non-www. I chose to remove the www from the URL.

Here's my .htaccess for that, including allowing for fonts to be accessed cross domain, as I had issues with this as well.

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Remove www
    RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
    RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

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

<FilesMatch "\.(eot|ttf|otf|woff|svg)">
    Header set Access-Control-Allow-Origin "*"
</FilesMatch>

Note!!! Once this is done, make sure to clear your Craft cache., especially if using fonts/font-icons.


How to loop through entries by importance? I have a channel of entries I'd like to loop through by order of importance on a scale of 1-5 with 5 being the most important and appearing first.

I tried to achieve this using a radio button field called importance and if else statements like:

{# List most important entries first #}
{% if entry.importance == "5" %}

            {% if entry.logo | length %}
                {% for asset in entry.logo %}

                {% endfor %}
            {% endif %}

{{ entry.companyName }}

{{ entry.description }}

    {% elseif entry.importance == "4" %}

                {% if entry.logo | length %}
                    {% for asset in entry.logo %}

                    {% endfor %}
                {% endif %}

{{ entry.companyName }}

{{ entry.description }}

        etc...

But this isn't very DRY and this lists the entries but they are still ordered by date. Is it possible to use .order with a field to achieve this?

Yes, you can use .order with any custom field, an example is below.

craft.entries.section( 'sectionHandle' ).order( 'customFieldHandle' )

For more info see the docs
https://craftcms.com/docs/templating/craft.entries#order


Display tag related to entry in current locale I've got this code snippet I'm working with and I can't get tags pulled out for related entry in current locale.

Maybe worth to mention, that tags is matrix field.

  {% set entries = craft.entries %}

  {% for entry in entries %}

{{ entry.title }}

  {% for tag in craft.tags.relatedTo({
          sourceElement: entries,
          sourceLocale: craft.locale
  }) %}

     { tag.title }}

     {% else %}

     No tags found

     {% endfor %}
     {% endfor %}

As pointed out in the comments to your question, there's no need
to specify the locale with your relatedTo parameter.

I already wrote you in response to your other question, Craft always works in one locale
only if you don't explicitly make it to do otherwise.

{% for entry in entries %}

{{ entry.title }}

    {% for tag in craft.tags.relatedTo(entry) %}

        {{ loop.first ? '
' }}

{{ tag.title }}

        {{ loop.last ? '
' }}

    {% else %}

No tags found

    {% endfor %}

{% endfor %}


How can I stop a duplicate entry being created & provide feedback? I have a booking form on my site, which when submitted creates a new entry which has two fields: an Entries field which links to a single User, and another Entries field which links to a single Event.

The title field of the entry is set automatically to "[date of event] - [username]".

The problem is that some users are booking twice for the same event. We need a way to limit bookings to ONE PER USER. Is there a way to prevent an entry with the same title being created, and rather than just failing to submit the form, give the user an error message saying "you can't book more than one place"?

Form:

<form method="post" action="" accept-charset="UTF-8" class="custom">
    <input type="hidden" name="action" value="entries/saveEntry">
    <input type="hidden" name="redirect" value="events/book/complete/{{eventID}}">
    <input type="hidden" name="sectionId" value="18">
    <input type="hidden" name="enabled" value="1">
    <input type="hidden" name="fields[userBooking][]" value="{{userID}}">
    <input type="hidden" name="fields[eventBooking][]" value="{{eventID}}">
    <input type="submit" value="Confirm Booking" class="button secondary">
</form>

Related question (possibly could be solved with the same answer) - I need to limit the number of bookings an event can take in total. So for example:

Event One: Bookings per user: 1, Total places: 35
Event Two: Bookings per user: 1, Total places: 50

This needs to be done with template code, not a plugin. Any ideas?

What about not showing the submit button at all, if a similar booking already exists?

{% if currentUser|length %}
    {% if entry.dateTime > now %} {# If event is in the future, display button to book #}

        {% set similarBooking = craft.entries({ sectionId: '18', relatedTo: ['and', { targetElement: currentUser, field: 'userBooking' }, { targetElement: entry.id, field: 'eventBooking' } ]}) %}
        {% set totalBookings = craft.entries({ sectionId: '18', relatedTo: { targetElement: entry.id, field: 'eventBooking' } }) %}

        {% if similarBooking|length %} {# Check if they have already booked #}

You have already booked a place for this event.

        {% else %} {# No previous booking, so check if there are spaces #}

            {% if entry.maxBookings > 0 %} {# Check if there is a limit on spaces #}

                {% if totalBookings|length < entry.maxBookings %} {# Check if there are spaces left #}
                    Book Now
                {% else %} {# There are no spaces left #}

This event is full.

                {% endif %}

            {% else %} {# No limit, display booking button #}
                Book Now
            {% endif %}

        {% endif %}

    {% endif %}

{% else %}
    Login to book
{% endif %}


Updates on live server without using Control Panel I'll freely admit to being a bit of a newb when it comes to SSH but wanting to start utilizing it more for my Craft3 sites. Maybe this is an irrelevant question but is it possible to update craft on the live server through ssh?

I'm ssh'd into my server and tried ./craft update all but I keep getting Permission denied.

composer update works fine though. Am I making a mistake or is it more of a hosting configuration issue?

You probably need to chmod +x craft on the craft executable so it an execute: https://askubuntu.com/questions/443789/what-does-chmod-x-filename-do-and-how-do-i-use-it/443799


Use a custom field type in Matrix Blocks - Craft 3 I'd like to create a field of type Dropdown/Table (or even use a field from a plugin like color-swatches) and have it available when selecting a matrix block element field type:

In this case, it's for creating a field containing a set of color values, a palette.

I'd like to know whether or not this is a common approach and what solutions do you usually give to this.

Thank you.

I'm not sure what it has to do with a matrix - you can use every field normally and inside a matrix, there is no restriction - but I usually create a custom field type.

You can see how to create Plugins in the documentation all available fields in Craft extends the base Field class

There are function like getInputHtml where you define the html that should be displayed while you create your entry/category and the function serializeValue that defines which value should be saved into the db.

You should take a look at the default Craft fields to get used to it. Change the values you need and create your own field.

However: I think the most common approach is to look what Pixel and Tonic does and understand how it works. Then you can create custom fields via Plugin or Module

Edit
You can see how to register custom fields here. As you can see they say the same

  You can refer to Craft’s own field classes for examples


In a template: Is there a way to call the parent's folder name? For Structured entries, I always have about the same folder structure.
If I could access the parent's folder name, I woudn't have to change the {% includes %} when copying a folder.

e.g.:

blog
---_common
---_entry
---_listing
---index

so _entry looks like this:

{% extends "_layouts/_layout" %}

{% block content %}
    {% include "blog/_common" %}
{% endblock %}

and _listing looks like this:

{% set params = { section:'blog', limit: gl_config.cf_blog_limit} %}
{% paginate craft.entries(params) as entries %}

    {% for entry in entries %}
        {% include "blog/_common" %}
    {% endfor %}

    {% include "_includes/_pagination" %}

{% endpaginate %}

They look almost the same for every structure channel I use (e.g. discography, pressreleases, projects etc etc.)

If I could use {% include "PARENT_FOLDER_NAME/_common" %}

I could just duplicate the folder and don't have to worry about these templates!

btw: the _common template looks about like this:

             {{ entry.postDate | date("d") }}
             {{ entry.postDate|date("F Y") }}

{{ entry.title }}

            {% set tags = entry.cf_blog_tags %}

            {% if tags | length %}
                {% for tag in tags %}
                    {{ tag.name }}
                {% endfor %}
            {% endif %}

        {#
            Content Matrix text / images / files / quotes / slideshows / videos etc..
        #}
        {% include "_includes/_content_blocks" %}

Permalink

        {# Edit #}
        {% include "_includes/_edit" %}

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.


Login Page Logo and Site Icon with Project Config How does one configure the rebrand options (Login Page Logo and Site Icon) with project config enabled? The fields to upload these files usually appear under Settings > General. This is only visible on environments where allowAdminChanges is set to true. How does one configure these on production environments where 'allowAdminChanges' => false is the norm?

System Settings don't support rebranding via Project Sync, however if you place your assets in the following locations and commit to GIT you can get similar results.

Login Page Logo -> <project_root>/storage/rebrand/logo/<filename>.svg
Site Icon -> <project_root>/storage/rebrand/icon/<filename>.svg

By placing the images in the above locations the system will automatically detect them. You should then see them show up in the backend without needing to upload them also.


Changed section from Channel to Structure, but can't re-order entries As the title says, I changed a section from Channel to Structure, but when clicking on that section in the dashboard, the layout still looks like a Channel, and I'm not able to reorder/drag the entries.

I've tried switching the section back to a Channel, and then again back to a Structure, with no change. Most of the entries were added since switching over to Structure, but they all still behave like Channel entries.

Have you switched sorting to "Structure"?

When you're not sorting by Structure, you won't be able to rearrange the entries.


Editing translation files from backend Is there any plugin that allows admin user to edit localization files from backend interface?

I think this plugin does what you want. It allows editing the translations for any static text passed trough Crafts translate functions & filters.


How to directly get value of text field in a given section of type structure? I am trying to get a value of a text field that is in a Section which is a structure and has multiple entry types. I don't want to use a loop. I tried this and some other variations but does not give me the correct value.

{% set value = craft.entries.section('mySectionHandle').type('entryTypeHandle').myTextFieldHandle.first() %}

What is the correct syntax? Thanks.

Try this:

{% set value = craft.entries.section('mySectionHandle').type('entryTypeHandle').first().myTextFieldHandle %}

{{ value }}

Just with your field handle at the end


Is it possible to output message on successful save with Guest Entries? I'm currently using the Guest Entries plugin with a front-end form to accept contact form submissions.

I'm just wondering if it's possible to output a message on a successful form being saved?

In an ideal world this might include the name of the submitter but failing that just a plain message informing the user that the form has been submitted.

(Previously I've been able to access the craft.request.getPost('name') but I don't think this works when using this plugin?

Thanks!

You could append a query string on your redirect url that you can then query for in your template. I've used this to display different messages for a new post or an edited post.

<input type="hidden" name="redirect" value="my-photos?message=photo-added">

{% set message = craft.request.getQuery( 'message' ) %}

{% if message|length and message == 'photo-added' %}

Thank's for uploading your image

{% endif %}

To use fields from the saved entry you could use a plugin and watch for the entries.onSaveEntry event that will fire when using the Guest Entries plugin.

craft()->on( 'entries.onSaveEntry', function( Event $event ){
  // Grab the entry from post request
  $entry = $event->params['entry'];

  // Add some conditionals so you only perform the redirect for the section you're posting to in the front end

  $name = $entry->getContent()->fieldName;

  // Render a template and pass the $name in
  //( not sure how to do this? )
});


How do I view / output the gateway response message? I'm working through the integration of a new Authorize.net gateway and bumping into errors trying to successfully process payments.

How do I view / output the response that's coming back from Authorize.net after the failed transactions in my template for debugging purposes?

I spit out {{ dump(paymentForm) }}, but I'm not seeing anything especially insightful.

Best to do this in your business logic plugin really, rather than in templates I'd say.

(You probably don't want to be passing this through to templates generally.  That said, you could easily add a template variable to this approach I guess...)

Here's some example code - and note what you get back will vary greatly depending on the gateway, so make sure you use defensive code like array_key_exists etc.

If you set an http session var, you can then retrieve this using a template variable:

    // Save the Beagle Anti-Fraud Score to the order
    craft()->on('commerce_transactions.onSaveTransaction', function ($event){

            $transaction = $event->params['transaction'];
            $order = $transaction->order;

            // Transactions are saved before responses too....
            if($transaction->response){
                craft()->httpSession->add("gatewayResponse", $transaction->response);
                BusinessLogicPlugin::log($transaction->response);

                //example of saving some of this data to a custom field in the order if you want to hang on to any of it...
                if (array_key_exists("BeagleScore",$transaction->response)){
                    $score = (string) $transaction->response['BeagleScore'];
                    BusinessLogicPlugin::log($score);
                    $order->setContentFromPost(["beagleScore"=>$score]);
                    BusinessLogicPlugin::log(craft()->commerce_orders->saveOrder($order));
                }
            }
     });

Then, to set it up as a template variable, something like this will work:

class YourPluginVariable
{
    public function gatewayResponse() {

        $return = "";
        $gatewayResponse = craft()->httpSession->get("gatewayResponse");

        if($gatewayResponse)
            $return = $gatewayResponse;

        craft()->httpSession->remove("gatewayResponse");

        return $return;
    }
}


Loop through an entry's fields and if the field type is "Categories" get that fields value/s In my plugin I need to loop through an entry's fields and if that field is a field type of "Categories" use that entry field value/s.

This is what I have tried so far.

if(array_key_exists('byCategory', $filterAttributes))
{
  foreach ($entry->getFieldLayout()->getFields() as $key)
  {
      $field = $key->getField();
      if($field->type == "Categories"){

         if(!$this->addFilterdCategories($field,$filterAttributes))
         {
             continue;
         }
      }
   }
}

I believe I have found the answer.

if(array_key_exists('byCategory', $filterAttributes))
{
  foreach ($entry->getFieldLayout()->getFields() as $key)
  {
      $field = $key->getField();
      if($field->type == "Categories"){

         if(!$this->addFilterdCategories($entry[$field->handle],$filterAttributes))
         {
             continue;
         }
      }
   }
}


How to run function after plugin installed? How can I run a function when my plugin is installed? I tried SafeUp in migrations but it doesn't work.

There's an event you can listen to:

use craft\events\PluginEvent;
use craft\services\Plugins;

        // Handler: EVENT_AFTER_INSTALL_PLUGIN
        Event::on(
            Plugins::class,
            Plugins::EVENT_AFTER_INSTALL_PLUGIN,
            function (PluginEvent $event) {
                if ($event->plugin === $this) {
                    // Do stuff here, we were just installed
                }
            }
        );

If you generate your plugin scaffolding via pluginfactory.io it will generate the above event for you in your base plugin.


Craft “Embedded Assets” Plug-in didn't save Embed in selected Asset Volume in CP i have 3 asset volumes in my craft install (3.1.5). If i want to create an embedded asset(Embedded Assets Plugin 1.0.2) in the first volume (CP) in my volume List than it appears in the second. Every Embed Asset appears in the second Volume!
What am I doing wrong?

Have you seen this: https://github.com/spicywebau/craft-embedded-assets/issues/95

Might be related and a fix is expected in Monday.


Adding a new block type to Matrix causes subfields and subfields of other block types to disappear When saving a newly added block type with subfields to an existing Matrix, the subfields of the new block type are gone and also are the subfields of 6 of the last block types. The whole Matrix contains 29 block types.

I'm using Craft CMS 2.6.2982.

Bumping php.ini's max_input_vars to a higher value as described in the answer here fixed it.


How can I make make the class of an entry link "active" if entry is the current url? I'm currently using the below jQuery but it's buggy as it relies on looking for 'similar' URL and not the exact URL.
Is there a way it can be done just using Twig?
{% set mainNavigation = craft.entries.section('mainNavigation').all() %}

    {% nav page in mainNavigation %}

            {% if page.customUrl|length %}
                {{ page.title }}
            {% else %}
                {{ page.title }}
            {% endif %}

            {% ifchildren %}

                    {% children %}

            {% endifchildren %}

    {% endnav %}

You don't need to use Javascript/jQuery for this.
You can get the the current url from craft.app.request in some way and do a check as you output your navigation.
It looks like you have some custom fields for urls but, For instance, if you wanted to check the last url segment you could use craft.app.request.segment(-1) to get it. Then when outputting your css classes, check it against whatever and output the active class.
{% set currentPage = craft.app.request.segment(-1) %}

then in your loop...

    Some title

You can also get the full URL with {{ craft.app.request.absoluteUrl }}
Or {{ craft.app.request.pathInfo }} to get the path


Not receiving emails from contact us and job application plugin to all email addresses on our domain Our web developers have setup and installed Craft on a VPS for a new website. When we fill out the contact us or Job application email recipient details; the emails never reach our email addresses, they also don't reach our messagelabs mail filter.
If I add another email address or a gmail account the emails are received just fine. I'm drawing a blank as to what the fault can be.

On MX Lookup blacklist check our domain and public IP are all clear. I've configured an A record to the IP of the VPS on our hosted DNS service. The VPS support have tested emailing us from the VPS (not the CMS) and emails come through.

Are there logs for Craft, is there a way I can see what's going on here.

Any help would be greatly appreciated.

D

As replied to the support ticket: Is the web server setup to handle emails locally for the domain (local delivery)? Your mail servers seem to live elsewhere so that could explain why you don't receive them yet gmail works fine.


Smart quotes in rich text fields? Is there a way to get the rich text field to automatically convert straight quotes to curly (smart) quotes? I'm not seeing anything on the redactorjs site or in the docs.

It turns out Smartdown should do the trick. It's a Craft plugin that adds MarkdownExtra and SmartyPants (the latter of which matters here) support to Twig.

SmartyPants is a rather ancient blogging plug-in from John Gruber for intelligently handling smart punctuation. Michel Fortin ran with it in the form of PHP SmartyPants, and most recently this Craft plugin by Experience.

Note: my first answer linked to a SmartyPants Craft filter by Experience that's apparently not finished. That one won't get you very far. :)


Using Supersort with date field I'm fetching entries from several different locales and merging them together into a single object.

I then want to sort these to be most recent entry shown first.
Using Supersort and the custom sortAs method I can get this to work showing entries in ascending date order:

{% set sections = 'news' %}
{% set locales = craft.i18n.getSiteLocales %}
{% set pages = [] %}
{% for locale in locales %}
    {% set entries = craft.entries.section(sections).status(null).locale(locale.id).localeEnabled(false).find() %}
    {% set pages = pages|merge(entries) %}
{% endfor %}
{% set pagesSorted = pages | supersort('sortAs', '{ postDate.date }') %}

However, if I try to use the above with the custom rsortAs method then it does not work, just returning the entries in the order they occur within the pages object.

Any thoughts on what might be doing wrong?

Thanks for asking about this, Cole!

There was a bug that was causing rsortAs to return erroneous results. The issue is fixed in the 1.0 release.

Grab yourself a fresh copy and you should be squared away.


Local MAMP site keeps redirecting to live production site I've imported a craft install and its database from a production site to make some changes to it. I've set it up to work locally in MAMP but whenever I go to example.local it keeps redirecting me to example.com. I'm using a multi-environment config so I'm not sure where it could be going wrong.

return array(

// Applies to all enviroments
'*' => array(

    // Base site URL
    'siteUrl' => null,

    // Environment-specific variables (see https://craftcms.com/docs/multi-environment-configs#environment-specific-variables)
    'environmentVariables' => array(),

    // Default Week Start Day (0 = Sunday, 1 = Monday...)
    'defaultWeekStartDay' => 0,

    // Enable CSRF Protection (recommended, will be enabled by default in Craft 3)
    'enableCsrfProtection' => true,

    // Whether "index.php" should be visible in URLs (true, false, "auto")
    'omitScriptNameInUrls' => 'auto',

    // Control Panel trigger word
    'cpTrigger' => 'admin',

    // Dev Mode (see https://craftcms.com/support/dev-mode)
    'devMode' => false,

    // Preserve Image’s Colour Profiles
    'preserveImageColorProfiles' => true

),

// Applies just to local dev server
'.local' => array(
    // Site URL
    'siteUrl' => "http://example.local:8888/",

    // Devmode
    'devMode' => true,

    // Turn off timeout
    'userSessionDuration' => false,

    // Image assets paths
    'environmentVariables' => array(
        'basePath' => '',
        'baseUrl'  => 'http://example.local:8888/',
    )
),

// Applies to production site
'.com' => array(
    // Site URL
    'siteUrl' => "http://example.com/",
    // Devmode
    'devMode' => false,

    // Image assets paths
    'environmentVariables' => array(
        'basePath' => '',
        'baseUrl'  => 'http://example.com/',
    )
)
);

And my current .htaccess

<IfModule mod_rewrite.c>
RewriteEngine On

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

There was a rule in my .htaccess to remove www that was redirecting to the live production site. Once I removed that I needed to delete my browser cache.


Implication of old task backlog suddenly being released I have a Craft website that has become quite big with several dozen sections and many templates - my first bigish Craft site - being a local government one with more than a thousand pages, forms and assets.

The Task Icon (I think is its name) had indicated there were uncompleted tasks and this has been stuck there for a couple of months while the site was being built and there have been many content and structure updates during this time.

Eventually I got around to attending to the issue after several half hearted attempts at finding out "what that stupid circle meant" (embarrassed much). A few minutes ago I followed the instructions at http://buildwithcraft.com/help/stuck-tasks and the task list was released like opening a flood gate - "hundreds"(?) of them suddenly ran, mostly "Resaving Meetings entries", Meetings being one of my sections, "Importing csv files" (which had consistently failed before, I now know why) plus "Updating element slugs and URIs". Also "Deleting stale template caches" which might explain another headache.

I'm now wondering if this will likely have any undesired impact on the site content given that I am now worried about old data replacing the new  via Imports, Resaving, and Updating that has carried on. I'm not a content editor on the site so I am not too familiar with what should be the right data set and business only opens again in about 12 hours.

Can anyone advise on what these tasks might do if run as a very delayed process?

The only time I can think of where this might be an issue is if you had a "Find and Replace" task that was part of the task backlog.  Those are triggered from the "Find and Replace" tool under Settings->Tools in the control panel.

Otherwise, you should be safe just letting the backed-up tasks finish catching up.


Routing and Segments I'm using the following code for now:

Route (in the control panel)
    recipes/{slug} loads _recipes/restaurant

In the template to define the restaurant and list its items
    {% set restaurant = craft.entries.section('restaurants').slug(craft.app.request.getSegment(2)).one() %}

How do I change it to {slug}-recipes to make it work?

Advanced routing (in routing file) is preferred for performance.

Thanks.

Route: {slug}-recipes

The in the template:

{% set parts = craft.app.request.getSegment(1)|split("-") %}
{% set newslug = parts[0] %}

Then you can use: .slug(newslug)


Issue with htaccess redirect adding parameters Having an issue with htaccess redirects adding parameters to the new locations. I have done some research on this and apparently its from the default htaccess rules. I have tried a few suggestions which fixes it, but then I run into another issue where all of my channels load without www so none of the css or scripts load. I have a redirect to redirect all non www to www, but for some reason it must be conflicting with my rules because it will not redirect the channels.

Here is my redirect code

<IfModule mod_rewrite.c>
RewriteEngine On
#only way the below redirects work without the parameter
RewriteRule (.+) index.php [QSA,L]

Redirect 301 /services/ http://www.domain.com/healthcare-it-services/
Redirect 301 /services/optimization/ http://www.domain.com/healthcare-it-services/optimization/
Redirect 301 /services/insurance-authorization/ http://www.domain.com/healthcare-it-services/insurance-authorization/
Redirect 301 /solutions/ http://www.domain.com/healthcare-it-solutions/
Redirect 301 /solutions/schedule-maximizer/ http://www.domain.com/healthcare-it-solutions/schedule-maximizer/
Redirect 301 /solutions/provider-network-manager/  http://www.domain.com/healthcare-it-solutions/provider-network-manager/

# send any asp page back to home
#RewriteRule \.asp$ http://domain.com [R=301,L]

RewriteCond %{HTTP_HOST} ^domain.com$
RewriteRule (.*) http://www.domain.com/$1 [R=301,L]

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

I was having a similar issue. Combining your use of:

RewriteRule (.+) index.php [QSA,L]

but with the following for the non-www redirect

RewriteCond %{HTTP_HOST} =www.domain.com
RewriteRule (.*) http://domain.com/$1 [R=302,L]

worked for me.


Show/display entries next/prev except entries with lightswitch field active I have projects on my portfolio that link to each other. I'm currently using previous and next links.

This is what my code looks like

{# Set parameters for prev/next elements list #}
{% set params = craft.entries.section('portfolio') %}
{# Get the prev/next elements #}
{% set prevEntry = entry.getPrev(params) %}
{% set nextEntry = entry.getNext(params) %}

And then I call it to display it in my code like so:

    {% if prevEntry %}

            Previous
            {{ prevEntry.client }}

    {% endif %}
    {% if nextEntry %}

            Next Project
            {{ nextEntry.client }}

    {% endif %}

My goal today is to hide the previous entry button if the previous entry has the comingSoon lightswitch field ON.

I got it by simply adding a condition where I was displaying my previous entry.

{% if prevEntry %}

    {% if prevEntry.comingSoon %}

        {# if comingSoon field is active, hide the link #}

    {% else %}

            Previous
            {{ prevEntry.client }}

    {% endif %}
{% endif %}


Autologin after frontend registration I have a frontend user account registration form and I d like to auto login the user automatically after the account creation.

So the user can choose a subscription plan and pay immediately after, without having to enter his login and password a second time.

I added the parameter 'autoLoginAfterAccountActivation' but it does not work.

Any idea ?

Oh my god I lost half the day on a syntax error !!

My general.php file had the line with true in quotes :

'autoLoginAfterAccountActivation' => 'true',

The correct line to have the parameter work is:

'autoLoginAfterAccountActivation' => true,


craft.request.getQuery returns empty on multi lingual site I have the strangest bug. I have a site with two languages, Norwegian and English. In my code i check for craft.request.getQuery('prodid'). Locally in Apache this works fine with both language URLs, but in production on Nginx, it only works on the Norwegian version (the main language).

The URLS looks like this

http://onepark.no/leie-parkering/paleet?prodid=1
http://onepark.no/en/rent-parking/paleet?prodid=1

For the english URL (the second) craft.request.getQuery('prodid') returns an empty string. For the Norwegian URL it returns "1".

Nginx rewrite code:

location / {
    try_files $uri $uri/ @rewrites;
  }

location /en/ {
   try_files $uri $uri/ @enrewrites;
  }

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

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

Turns out the problem was with the Nginx config as Brad suggested. There was a question mark behind the p=$1. When we removed the ? and restarted PHP it worked.

location / {
    try_files $uri $uri/ @rewrites;
  }

location /en/ {
   try_files $uri $uri/ @enrewrites;
  }

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

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


Craft 3 multi-site route to template (no entry) I have a Craft 3 multi-site site - / for the main site, /site1/ for site1, etc. I have a template templates/foo.twig, and /foo hits it for the main site, but /site1/foo does not hit it for site1. I think it should. What am I doing wrong?
I am trying to get case 4 of the Routing algorithm to work with multiple sites:

Does the URI match a template?

Finally, Craft will check if the URI is a valid template path. If it is, Craft will return the matched template. Note: if any of the URI segments begin with an underscore (_), Craft will return a 404. Craft hides from direct access any template path segments that begin with an underscore.

I don’t think it has something to do with URI to template routing. It should just work once you have your sites setup correctly in Craft and in server configurations.

What you can do to test correct site setup in Craft is to request the page using the query string:

https://example.com/site1/?p=foo


Is it safe to mass delete users from the database directly We have a client site that has been getting a lot of spam registrations. We're turning on purgePendingUsersDuration to help deal  with some of these automatically, but I was planning to go into the database to delete a bunch in bulk directly (since there are almost 200 of them)

Is it safe to delete them just from craft_users and craft_usergroups_users tables? Are there other places I should watch out for?

If you want to delete users (or any other elements in Craft) directly from the database, the place to do that is the elements table. Delete the row(s) from there, and all the elements’ rows in the other tables will go away automatically.


My `for` loop has fallen...and it can't get up I want my
 to show a single tag representing all "active" entries ( "active" using a custom lightswitch field in the entry: fellowStatus.

Each tag is a year (e.g. 2014, 2010, etc)

E.g. if there are no "active" entries with the tag 2017, it should not display.

The code block below spits out only tags where entries are "active"
BUT...
It spits out duplicates of each tag depending on how many entries are using it. (e.g. It displays 8 instances of 2015 instead of 1)

{% for entry in craft.entries.section('fellows').limit(null) %}

  {% set tags = craft.tags.relatedTo(entry).limit(1).find() %}
  {% set active = entry.fellowStatus %}

    {% if entry.fellowStatus == 0 %}

      {% for tag in tags %}

            {{ tag.title }}

      {% endfor %}

    {% endif %}

{% endfor %}

First: grab all entries that match your criteria

Second: grab all Tags related to your entries

PHP

$entryIds = Entry::find()
    ->yourTagField(':notempty:')
    ->fellowStatus('1')
    ->section('fellows')
    ->ids();
$tagsRelatedToEntries = Tag::find()
    ->relatedTo($entryIds)
    ->all();

Twig

{% set entryIds = craft.entries
    .section('fellows')
    .fellowStatus('1')
    .yourTagField(':notempty:')
    .ids()
%}
{% set tags = craft.tags.relatedTo(entryIds).all() %}


Display Items in customer order in a particular order Is there a way to sort the customer items by item number under commerce customer orders in the control panel?

There is no current built-in solution for this.  I suspect they are displayed in the order they were added to the cart most likely.

Your best hope would be something like the cpjs addon and some magic JS to swap the rows, but it would be...non-trivial at best.

https://github.com/lindseydiloreto/craft-cpjs

You might want to put in a feature request here:
https://github.com/craftcms/commerce/issues


Unable to update Craft: 'requires yiisoft/yii2-queue 2.1.0' I've got another update issue with the following error. Can anyone help?

    craftcms/cms 3.0.27 requires yiisoft/yii2-queue 2.1.0 ->
    satisfiable by yiisoft/yii2-queue[2.1.0] but these conflict with your requirements or minimum-stability.

composer.json looks like this

{
"name": "craftcms/craft",
"description": "Craft CMS",
"keywords": [
"craft",
"cms",
"craftcms",
"project"
],
"license": "MIT",
"homepage": "https://craftcms.com/",
"type": "project",
"support": {
"email": "support@craftcms.com",
"issues": "https://github.com/craftcms/cms/issues",
"forum": "https://craftcms.stackexchange.com/",
"source": "https://github.com/craftcms/cms",
"docs": "https://craftcms.com/docs",
"rss": "https://craftcms.com/changelog.rss"
},
"require": {
"craftcms/cms": "3.0.23.1",
"vlucas/phpdotenv": "v2.4.0",
"craftcms/ckeditor": "1.0.0-beta.2",
"craftcms/redactor": "2.1.6",
"cebe/markdown": "1.1.2",
"composer/ca-bundle": "1.1.1",
"composer/composer": "1.6.3",
"composer/semver": "1.4.2",
"composer/spdx-licenses": "1.3.0",
"craftcms/oauth2-craftid": "1.0.0.1",
"craftcms/plugin-installer": "1.5.2",
"craftcms/server-check": "1.1.1",
"creocoder/yii2-nested-sets": "0.9.0",
"danielstjules/stringy": "3.1.0",
"doctrine/lexer": "v1.0.1",
"egulias/email-validator": "2.1.4",
"elvanto/litemoji": "1.3.1",
"ezyang/htmlpurifier": "v4.10.0",
"guzzlehttp/guzzle": "6.3.3",
"guzzlehttp/promises": "v1.3.1",
"guzzlehttp/psr7": "1.4.2",
"justinrainbow/json-schema": "5.2.7",
"league/flysystem": "1.0.44",
"league/oauth2-client": "2.2.1",
"mikehaertl/php-shellcommand": "1.2.5",
"paragonie/random_compat": "v2.0.12",
"pixelandtonic/imagine": "v0.7.1.3",
"psr/http-message": "1.0.1",
"psr/log": "1.0.2",
"seld/cli-prompt": "1.0.3",
"seld/jsonlint": "1.7.1",
"seld/phar-utils": "1.0.1",
"swiftmailer/swiftmailer": "v6.0.2",
"symfony/console": "v3.3.6",
"symfony/debug": "v3.3.6",
"symfony/filesystem": "v3.3.6",
"symfony/finder": "v3.3.6",
"symfony/polyfill-mbstring": "v1.8.0",
"symfony/process": "v3.3.6",
"yiisoft/yii2": "2.0.15.1",
"yiisoft/yii2-bootstrap": "2.0.8",
"yiisoft/yii2-composer": "2.0.6",
"yiisoft/yii2-debug": "2.0.13",
"yiisoft/yii2-queue": "2.0.2",
"yiisoft/yii2-swiftmailer": "2.1.1",
"zendframework/zend-escaper": "2.6.0",
"zendframework/zend-feed": "2.8.0",
"zendframework/zend-stdlib": "3.2.0",
"solspace/craft3-freeform": "2.4.0",
"dolphiq/redirect": "1.0.18"
 },
"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');\""
],
"post-create-project-cmd": [
  "@composer dump-autoload -o",
  "@php craft setup/welcome"
]
}
}

How about changing the yii2-queue version number in composer.json and then running a composer update?


Is it possible to set a new route for a plug-in CP section in Craft 3? Is it possible to use a custom route for your plugin's CP section, instead of cpTrigger/plugin-handle, or to direct cpTrigger/plugin-handle to a different template other than plugin-handle/index.twig?

Of course you can Link

Event::on(UrlManager::class, UrlManager::EVENT_REGISTER_CP_URL_RULES, function(RegisterUrlRulesEvent $event) {
    $event->rules['whateveryoulike'] = ['template' => 'cocktails/_edit'];
    $event->rules['cocktails/<widgetId:\d+>'] = 'cocktails/edit-cocktail';
});

So the url www.example.com/admin/whateveryoulike redirects you to the template cocktails/_edit. You don't need to use the plugin-handle, you can overwrite everything but you have to make sure no other plugin overwrites your routes..


Plugin Use Default Value When Empty I've got a default value defined in my model for a field

'limit' => array(AttributeType::Number, 'default' => 0)

When I create a new record, if the limit field is empty, NULL gets stored in the DB instead of 0. I thought $model->setAttributes() would set the default values if the values coming in were NULL. What am I missing?

If you want to add a default to an existing column in a table in a migration, you'd do something like this:

$this->alterColumn('tableName', 'columnName', array('column' => ColumnType::Number, 'default' => 0));

If you want to add a default to a new column in a table in a migration, you'd do something like this:

$this->addColumn('tableName', 'columnName', array('column' => ColumnType::Number, 'default' => 0));


How can I work with related entries within a Matrix in a plug in? I have a Matrix field named "skillLevels" with a single block type.
Each row has 2 fields, "skillName" and "skillLevel"

skillName is a relationship to another entry (Skills)
skillLevel is a simple integer.

I am building a custom plugin which takes post data from a form.
The form contains an entry ID ($groupId), a skill name and a value to use to modify the level of that skill.

$groupEntry = craft()->entries->getEntryById($groupId);

    $skillLevels = $groupEntry->skillLevels;

    foreach($skillLevels as $skill){
       $skillLevel = $skill->skillLevel; // outputs the skill level
       $skillName = $skill->skillName; // this doesn't work
    }

$skill->$skillLevel gives me the integer stored in that field.
But $skill->skillLevel does not gives me a model. I then tried using $skill->skillLevel->id but still no luck.

How can I look through the Matrix rows to find the row that matches the skill name coming from the form Post data?

It’s an entries field, so $skill->skillName returns just the ElementCriteriaModel prepared to query for one or more elements matching the criteria.

You need to do something like this:

$entry = $skill->skillName->first();
$skillName = $entry ? $entry->title : null;


User registration plugin listening How can I listen in my plugin to see if

craft()->on('users.saveUser', function(Event $event) {

onsaveUser came from front end creation or control panel ?

You can use the request service. craft()->request->isCpRequest() or craft()->request ->isSiteRequest()

https://craftcms.com/classreference/services/HttpRequestService#isCpRequest-detail


What would cause a user's activation link to fail? I've just rolled out some changes to a site that's now seeing a big increase in (front end) user sign ups.

I have activation by email on and I'm tracking in analytics the number of hits to the activation success and activation failed pages.

If I look at yesterday as an example, 168 Success and 15 Failed.

I'd like to start working on bringing this down, but it would be useful to know the scenarios that would cause a user to hit the failed page. I believe they'll get this if they, for example, click the activation email twice.

Is there any other obvious causes that I use as a starting point?

Thanks!

They could already be active Users
Their activation link could have timed out

1) happens more often than I'd think, people try using it as a way of "getting to the site again"

2) Can be controlled in /config/general.php - https://craftcms.com/docs/config-settings#verificationCodeDuration


Craft CMS 3 Installed but not working I have a remote repository with a Craft install and am trying to pull it to a new environment. I run the composer install and Craft & other packages install seemingly correctly, added the .env file and set up the Apache server to point to the /web folder.
When I load up the url I get a visual of the index.php file:

  // Set path constants define('CRAFT_BASE_PATH', dirname(DIR));
  define('CRAFT_VENDOR_PATH', CRAFT_BASE_PATH.'/vendor');

  // Load Composer's autoloader require_once
  CRAFT_VENDOR_PATH.'/autoload.php';

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

  // Load and run Craft define('CRAFT_ENVIRONMENT',
  getenv('ENVIRONMENT') ?: 'production'); $app = require
  CRAFT_VENDOR_PATH.'/craftcms/cms/bootstrap/web.php'; $app->run();

No urls seem to be working e.g. /admin or /index.php?p=admin/install and I can even put anything as the url and nothing errors, just shows this file still.

Your answer didn't end up working for me, but I did get it working.

Update (or add) "vlucas/phpdotenv": "^5.0" to composer.json
Edit the craft (or index) file's contents:

// Load dotenv?
// if (class_exists('Dotenv\Dotenv') && file_exists(CRAFT_BASE_PATH.'/.env')) {
//     Dotenv\Dotenv::create(CRAFT_BASE_PATH)->load();
// }
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
if (file_exists(CRAFT_BASE_PATH.'/.env')) {
  $dotenv->load();
}

I can then retrieve my environment vars with:
$varOne = $_ENV['VAR_ONE'];
$varTwo = $_SERVER['VAR_TWO'];


Can two sites use the same channel, but have unique entries? I have a multi-site application where my primary site is my company's main website, and the additional sites are small "microsites" for some of our projects.

I want to share channels between my sites. For example, I have a "testimonials" channel with a basic quote & cite fields in the entry type.

I want to make this channel available to all my sites, but I want each site's testimonials to be unique, since they're about different projects. I also don't have the same number of testimonials for each site.

I made the channel available to each site, then created the testimonial entries within each site's tab. I thought this would keep each site's testimonial entry list separate, but it instead made one big list.

Is there a way that I can do this through filtering or site groups? I don't want to have to create a unique channel for each site that has the exact same functionality.

Edit: I've found that I can fudge this by using the "Enable for this site" lightswitch on each entry, but I don't trust my content editors to properly use this function, and I don't want them to have to see all the disabled entries from other sites in the entry list.

There is a light switch field in your section settings with the label "propagate entries across all sites". Just turn it off and your entries will be unique


How do I print the field ID of a category field in place of its title? How do I print the field ID of a category field in place of its title?

{% for entry in craft.entries.section('posts').relatedTo(category) %}
    some html...
    {% for category in entry.market.level(2).find() %}
        {{ category.title }}
    {% endfor %}
{% endfor %}

I want to print the field ID of category.title instead.

Reason = I am using the printed output as a class to filter against.  Some of the category titles contain more than one word and I do not want to add a hyphen to each instance.   So, using the field ID in place of category.title  would solve this problem.


Element API User example I am attempting to build an application where Craft handles all of the API based data (JSON). I am using the Element API. I can't find an example anywhere online that outputs Users.

I am trying to output some basics first before I start outputting the custom Matrix fields etc. Here is my elementapi.json:

<?php
namespace Craft;

return [
    'endpoints' => [
        'players.json' => [
            'elementType' => 'User',
            'criteria' => ['group' => 'player'],
            'transformer' => function(EntryModel $entry){
                return [
                    'username' => $entry->$username,
                    'jsonUrl' => UrlHelper::getUrl("player/{$entry->id}.json")
                ];
            },
        ]
    ]
];

Any help or an example with some custom matrix user fields would be much appreciated! Thanks a bunch!

If you set the elementType to User, then the transformer will have a UserModel object passed in like so:

<?php
namespace Craft;

return [
    'endpoints' => [
        'players.json' => [
            'elementType' => 'User',
            'criteria' => ['group' => 'player'],
            'transformer' => function(\Craft\UserModel $user) {
                return [
                    'username' => $user->username,
                    'jsonUrl' => UrlHelper::getUrl("player/{$user->id}.json")
                ];
            },
        ]
    ]
];


What do some Craft permissions mean? I'm documenting Craft permissions for internal use but there are some permissions that I'm not clear on.

"Access the site when the system is off" What system?
"Publish live changes" How can you do that?

Access the site when the system is off means that a logged in user with that permission can view the website front end (I think - never actually used this). You can set the system status in Settings > General, or via the craft/config/general.php file using 'isSystemOn' => true/false.

If a user doesn't have "Publish live changes" it means that the user can create new entries, but they can't appear on the front end of the site because they can't set the entry status to be published (the green lightswitch button on all Entries). This means you can review their content as a more privelidged user before they get made public.


Recommendations for Form Integrations with Salesforce? I'm new to Craft and really loving it so far. I'd like to use something like Sprout Forms or Freeform (are there others worth looking at?) but I really need to be able to submit any data to Salesforce.

I know Freeform has a Salesforce integration but from talking with support it sounds like it only works with Leads and I need custom Object support.

i.e. we have job application forms and other applications that use custom Objects and from time to time we do add others.

With Sprout Forms I've been looking into Payload Forwarding and what I could maybe do with that.

Does anyone have any experience with this and any recommended approaches? I'm more of a Front-End Dev so looking at something I could sort myself but if not I'll be looking at hiring someone to help me pull a solution together.

Sprout Forms it's a good option for your requirements, using the Payload Forwarding you'll be able to send the data to an endpoint on salesforce, you can also use the Hidden Field or the Invisible Field from the Sprout Fields plugin to setup any pre-filled API-keys if required.


Problem saving new entry populated with setContentFromPost() while setContent() works I'm building a cinema program, and I'm trying to build entries for movies and shows loading external data via a plugin.

I'm getting close, but now I've hit a roadblock trying to save the entries. I build an array of the data to set as content that looks something like this:

$movie = [
  'movieID'       => (int)$ctx_movie['MOVIE_ID'],
  'title'         => $ctx_movie['VERANSTALTUNGSTITEL'],
  'audioLanguage' => $ctx_movie['SPRACHVERSION'],
  'country'       => $ctx_movie['COUNTRY'],
  'director'      => $ctx_movie['DIRECTOR']
]

Then I make an entry model, and try to set the content to the above array:

$entry = new EntryModel();
$entry->sectionId = craft()->sections->getSectionByHandle('movies')->id;
$entry->typeId    = craft()->sections->getSectionByHandle('movies')->type('movie')->id;
$entry->authorId  = craft()->userSession->getUser()->id;
$entry->enabled   = true;

// This doesn't work:
$entry->setContentFromPost($movie);

// This seems to work, creating an entry and populating fields:
// $entry->setContent($movie);

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

I keep getting this error for every entry:

array ( 'title' => array ( 0 => 'Name cannot be blank.', ), )

The value I set to the 'title' element definitely has a value, and even if I hard code it to be a dummy string, it still fails in the same way.

It seems to work when using setContent($movie) instead of setContentFromPost($movie), but from what I've read the latter is the correct (or best practice) way to do it.

I'm guessing it has something to do with the extra validation, but I can't for the life of me understand why a simple string like 'Dummy title' fails the same way as my variable. The name setContentFromPost throws me off a bit, as I'm unsure if it means the data should come via a post request, but it seems to be fine with my other variables, and from the documentation they seem to be used in the same way, passing an array of values.

(On a side note, I got a similar error for a field that is of type dropdown. I guess here I just haven't understood what value to pass to a dropdown fieldType, so if someone has any tips here too, that would also be great, but I assume it may be two different issues.)

I believe that setContentFromPost can only be used to set the content of custom fields on an EntryModel, not standard fields such as title.

Instead, you need to use $entry->getContent()->title to set the title on the EntryModel.

So your code would look like this:

$movie = [
  'movieID'       => (int)$ctx_movie['MOVIE_ID'],
  'audioLanguage' => $ctx_movie['SPRACHVERSION'],
  'country'       => $ctx_movie['COUNTRY'],
  'director'      => $ctx_movie['DIRECTOR']
];

$entry = new EntryModel();
$entry->sectionId = craft()->sections->getSectionByHandle('movies')->id;
$entry->typeId    = craft()->sections->getSectionByHandle('movies')->type('movie')->id;
$entry->authorId  = craft()->userSession->getUser()->id;
$entry->enabled   = true;

// Set the title directly on the $entry
$entry->getContent()->title = $ctx_movie['VERANSTALTUNGSTITEL'];

// This should now work:
$entry->setContentFromPost($movie);

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


Unable to login on multi-node install We have a single DB and multiple web servers and are finding that unless we enable sticky sessions on the load balancer, we aren't able to login (or we can login then lose the session).

I can see a sessions table and there appears to be no config setting, so what might be going wrong here?

Do we need to set overridePhpSessionLocation to false?

As of Craft 2.3, overridePhpSessionLocation is set to false by default.  Meaning that wherever Apache (or whatever web server you're using) and PHP is configured to save the PHP session files, that's where they will go.

If you set overridePhpSessionLocation to true, then the session files will be saved in craft/storage/runtime/session. Just be aware there is a bug in PHP that will prevent session garbage collection from running if you override the default session save path (which is what that config setting does). So you'll want to provide your own external method of session file garbage collection.

So, your options are to 1) enable sticky session as the load balancer level to ensure that a user will always get sent back to the same server that their session was created on or 2) provide an external shared storage drive that all of your web servers can write the PHP session files and point each web server to use that.

Personally, I'd just enable stick sessions.


Can I have non-boolean TargetBlank output using HTMLPurifier and the Redactor plugin? I'm using the Redactor plugin throughout a Craft 3 site and I'm also using a custom HTML Purifier config to clean up the HTML (surprise).

{
  "HTML.ForbiddenElements": ["&nbsp;", "br"],
  "AutoFormat.RemoveEmpty.RemoveNbsp": true,
  "AutoFormat.RemoveEmpty": true,
  "AutoFormat.Linkify": true,
  "AutoFormat.RemoveSpansWithoutAttributes": true
}

However it looks like it overrides Redactor's link target blank option and that override is either on (open in new tabs) or off (strip target blank).

Is there any way I can give that choice back to the user? Maybe I can stop Craft using the full url for links other than external links?

And this solved the problem:

"Attr.AllowedFrameTargets": ["_blank"]


Modifying the search order “Score” criteria I'm a Craft newbie, just searching for something and spotted this related post Search order "Score" criteria

What I would like to know, is there a way to add a Modifier value to a field, like LOW Search does for EE?

For example; lets imagine we want trees listed first.

We would add a 'keyword' field, and a modifier value too help ensure a far higher score than any other fields, possibly including the title.

So an entry with the words 'Top Trees' in our 'keyword' field would trump all other entries containing the words 'Top Trees'.

There currently isn't a native way to do this, and I'm not sure it'd be that easy for a plugin to easily pull off either, since there currently aren't any search related events exposed in Craft.

Probably worth adding a feature request for, though!


Use en-US instead of en_us locale code I want to use locales like en-US instead of en_us.
Is there a way to do this other than creating totally new locales?
Can I set it up at the siteUrl ?

When defining your siteUrl, you can do:

return array(
    // ...
    'siteUrl' => array(
        'en_us' => 'http://example.com/en-US/',
        // ...
    ),
);


Sort entries by custom date in Matrix field / Super Table I currently have numerous Super Tables with date fields inside and I am trying to get all table items to list themselves together in date order depending on what the user inputs. I have tried using the Super Sort plugin but haven't had any luck.

Not sure if there is somewhere below where I have gone wrong or misunderstood the documentation. The plugin I am trying to use can be found here

Does anyone know if this is possible with Super Tables or Matrix fields?

The error I'm currently getting is:

  Object of class Craft\ElementCriteriaModel could not be converted to string

protected function doDisplay(array $context, array $blocks = array())
{
  echo $this->getAttribute($this->getAttribute(($context["object"] ?? $this->getContext($context, "object")), "tourDates", array()), "tourDate", array());
}

if (version_compare(PHP_VERSION, '7', '>=') && $code === 2 &&
strpos($message, 'should be compatible with') !== false)
{
    return;
}
parent::handleError($code, $message, $file, $line);

protected function displayWithErrorHandling(array $context, array
$blocks = array())
{
    try {
        $this->doDisplay($context, $blocks);
    } catch (Twig_Error $e) {
        if (!$e->getSourceContext()) {
            $e->setSourceContext($this->getSourceContext());
        }

This is the code I current have:

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

{% for entry in entries %}

    {% if entry.tourDates %}
        {% for row in entry.tourDates %}
            {{ row.tourDate|date("d/m/Y") }}
        {% endfor %}
    {% endif %}

{% endfor %}

I have also tried:

{% set entries = artists | supersort('sortAs', '{ tourDate }') %}

and

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

I did something like this as a workaround:
Loop over entries, fetching all data you need and adding it to an array. Sorting that array with SuperSort and than displaying all info by looping over the array.

{% set tourDates = [] %}
{% set artists = craft.entries.section('artists') %}
{% for artist in artists %}

    {% if artist.tourDates %}
        {% for row in artist.tourDates %}
            {% set tourDates = tourDates|merge([ {
                'tourDate' : row.tourDate|date("d/m/Y")
            } ]) %}
        {% endfor %}
    {% endif %}

{% endfor %}

{% set tourDates = tourDates | supersort('sortAs', '{{ object.tourDate }}') %}

{% for tourDate in tourDates %}
    {{ tourDate.tourDate }}
{% endfor %}


What accurately will set asset paths for multilingual sites? This is actually a fairly crucial matter, since relative paths definitely won't work with languages, unless you really want all assets in a given Source to be localized or at least copied to each language folder. As well, hard paths in the CP will fail with multi-environment config where dev, staging, and deployment sites can have different full storage paths.

Things may appear to operate at first with relative paths, for example, and it may feel like a safe way from experience with other systems, but then you'll find that features like automatic generation of image transforms that you've set up (icons, controlled sizes, etc.) will fail.

If each locale uses the same TLD but uses a subfolder for localized content (i.e. example.com/en, example.com/de, etc.). You can move between development, staging, and production environments without having to change settings in the admin panel by simply using an absolute path in the Admin assets source URL setting (i.e. /assets/img/uploads) and a relative path for the File System Path there (i.e. ../public_html/assets/img/uploads).

For more complicated setups, such as independent site URLs (i.e. example.com, example.co.uk, etc) for each locale, I've set asset paths by setting an assetsUrl environment variable in general.php like so:

'example.com' => array(
    'environmentVariables' => array(
        'siteUrl'        => '//example.co.uk/',
        'assetsUrl'    => '//example.com/'
    )
)

Then in the Admin panel's assets source settings, I set a relative path for the File System Path and use the {assetsUrl} environment variable for the URL.

With this setup you can also move between development, staging, and production environments without having to change settings in the admin panel.

Once {assetsUrl} is set in the Admin panel for the URL, writing {{ file.url }} in your template will return the full URL using the assets source URL setting.

Or, you can link to assets (e.g. scripts) in your templates using the assetsUrl environment variable.

{{ craft.config.environmentVariables['assetsUrl'] }}assets/js/main.js


Booking system based on Charge 2.0 I am building an event booking system for a restaurant using Charge 2.0. Everything is working great, but having problems implementing a feature that shows how many spots are left.

An Event channel entry (created by the restaurant) provides parameters such as price, event name, etc and passes them to a Charge form. The Event entry also includes a field that specifies the maximum number of guests.

The Charge form includes a field for specifying a 'number of guests' for the booking. To indicate how many spots are left, we first need to calculate how many guests have already been booked, which is a simple matter of getting the 'numberOfGuests' field from all of the existing Charge entries and summing them. The problem arises when trying to filter the results using a Search parameter, which limits the entries to a specific event (the Event name is passed to the Charge description field). Here is a bit of the code:

{% set q = 'description:' ~ '"' ~ entry.title ~ '"' %}
{% for entry in craft.charge.charges().search(q) %}
   //get the number of guests

I tried a few different things, including a wildcard search, and none of them return any results. Does anyone know if the Charge model supports a Search parameter?

Developer of Charge here.

Yes - Charge supports all the native Craft criteria search parameters for fields.

Like you mentioned, there are a few special fields that aren't supported currently within that. Those are fields like description, notes etc.. The supported direct attributes on the Charge model that can be searched (in addition to all the basic ElementType attributes) are :

userId
sourceUrl
timestamp
hash
customerId
mode
meta

This is in addition to all Craft fields you might have attached to the charges.

For example - if I wanted to find all the charges based on a specific customerId (the stripe identifier), it'd look something like this :

{% set charges = craft.charge.charges({ customerId : 'cus_00000000' }) %}

They can be of course be combined, so all charges for that customer only in live mode :

{% set charges = craft.charge.charges({ mode: 'live', customerId : 'cus_00000000' }) %}

If we had a field on the charge model with a name of ourCustomField, we could search for that like :

{% set charges = craft.charge.charges({ search : { query : 'ourCustomField:' ~ someSearchValue }}) %}

And also, we could combine all those into a single thing too:

{% set charges = craft.charge.charges(
   { mode: 'live',
     customerId : 'cus_00000000',
     search : {
        query : 'ourCustomField:' ~ someSearchValue
   }}) %}

Or in the alternative syntax, that could be:

{% set q = 'ourCustomField:' ~ someSearchValue %}
{% set charges = craft.charge.charges()
      .customerId('cus_00000000')
      .mode('live')
      .search(q) %}


Set max-height on image transforms? Is it possible to define an aspect ratio / set a max height on an image transform, without using a plugin?

Let's say the width is fixed to 600px, but the height can be any value up to 800px?

You can pass an array instead of the image-transform handle to the getUrl() function

{% set transform = {
    'width' => 600,
    'height' => (asset.getWidth() <= 800)? asset.getWidth() : 800
} %}
{{ asset.getUrl(transform) }}


How can I use asset select modal in utility? I created a custom utility template. Inside the template, I would like to use the built-in asset select modal for the "Add image" button. Any way to do this please?

The field is just a normal ElementSelect field with the element type craft\\elements\\Asset

{{ forms.elementSelectField({
    label: "Asset"|t('app'),
    id: 'assetSelect',
    name: 'assetSelect',
    elementType: 'craft\\elements\\Asset',
   selectionLabel: "Choose"|t('app'),
   elements: elements, //array of selected elements
 }) }}


Date/Time field outputting time with additional minutes I've having an issue where a Date/Time field (time only) is outputting the time in the front-end template with an extra 10 minutes.

In my template I'm using entry.startTime|date("g:ma”).

In the DB the field_startTime for the entry is 2016-10-15 16:00:00, but on the front-end I’m seeing 4:10pm.

Could anyone tell me where are these extra 10 minutes coming from, please?

This is happening both locally and on the dev server, using Craft CMS 2.6.2949

You are using the wrong variables.

The 10 is there because it means October not 10 minutes.

You have to use | date("g:ia”).


Is it possible to update a Freeform submission via twig? I'm making a google map feature where you type in a search and it drops a pin on the map (standard stuff).
I want to log all the searches for reporting. So, I'm using a Freeform form to collect the location search and display a map on the result page (using the token approach to get the submission info). The result page uses Smart Map to turn the search into a lat/lng and then render the map. I've got that all working great.
What I'd also like to do, for reporting purposes, is to update the Freeform submission with the lat and lng that gets calculated on the result page.

I haven't found a way to update a submission via twig in the docs. Is this possible? Or are there alternative approaches I should consider?

Update: Solspace informed me this could be accomplished with a custom module and using a Freeform event, specifically this one:
https://docs.solspace.com/craft/freeform/v3/developer/submission-events.html#before-a-submission-is-submitted".
So, in my example, I will need to move my lat/lng logic into the custom module so it happens before the submission is submitted. Then, on the result page, grab the lat/lng from the submission data.


Query for blocks across Block Types using the new field parameter? This is a great new feature of Craft 2.3:

  It is now possible to set custom field parameters on Matrix block queries.

I was wondering what would happen, if two or more Matrix Block Types had a field with the same handle (e.g. myLightswitchField), and if it was possible to query for blocks across Block Types using this field as a parameter.

My example code doesn't return any blocks:

{% set blocks = entry.myMatrixField.myLightswitchField('1') %}

Yeah! There's {{ blocks|length }} Matrix blocks enabled.

This is just an example! I know that you can disable blocks from the block's context menu.

Unfortunately this is a limitation of that feature. In this case, both of your Lightswitch fields will be tweaking the DB query with their own WHERE [field_column_name] = 1, without knowledge of each other.

To avoid this, just give each of your Lightswitch fields their own unique handles.

If you want to get all the blocks where either one of your Lightswitch fields are checked, you could do this:

{% set blockIds = entry.matrixField.type('type1').typeOneLightswitchField(1).ids()
    |merge(entry.matrixField.type('type2').typeTwoLightswitchField(1).ids())
%}

{% for block in entry.matrixField.id(blockIds) %}
    ...
{% endfor %}

Not exactly a clean solution, but it’ll get the job done.


craft.entries and :first-letter I want to display the first character in a paragraph with a drop cap. It works fine with normal text or setting it with js, but when I use an entry field it doesn't pull out the first character. The code looks like this:

// css
p.dropcap {
float: left;
font-size: 4em;
…
}

// html

{{ entry.body }}

The first letter isn't dropped, but if I change the html to:

This is {{ entry.body }}

The T is dropped as expected.

Any ideas on how to fix this?

Rich Text fields always return the paragraphs wrapped in <p> tags. So you would have to use an additional <div> element and apply the dropcap styles to the first <p> tag within that <div> using the first-of-type pseudo-class.

<div class='dropcap'>
    {{ entry.body }}
</div>

.dropcap p:first-of-type:first-letter {
  float: left;
  font-size: 4em;
  line-height: 3em;
}


How to pass the matrix attributes to views without too much ceremony Consider the following example:

master.twig

{% for module in entry.main_contents %}
  {% include '_modules/' ~ module.type with module only %}
{% endfor %}

my_awesome_module.twig

<h1>{{ title }}</h1
{{ content | raw }}

In my case obviously I get the twig error Argument 1 passed to Twig_Template::display() must be of the type array
because I cannot pass objects to the include function. In your examples you use the following solution:

master.twig

{% for module in entry.main_contents %}
  {% include '_modules/' ~ module.type with {'data': module} only %}
{% endfor %}

my_awesome_module.twig

<h1>{{ data.title }}</h1
{{ data.content | raw }}

Isn't there a way to pass directly the matrix attributes without encapsulating them in an other array?

p.s.

I hooked in also a twig helper method that returns $model->getContent()->getAttributes() but it seems that the array returned looses all its nested properties ( like the assets list...)

The short answer is no.

The longer answer is you will probably get used to it. Craft twig templates in general look like {{entry.title}} (or {{data.title}}) rather than just {{title}}. I find it easier to read, though you may not.


How to immediately redirect to an entry after creating the new entry from a frontend form? I'm using a frontend form to create an entry with {{ actionInput('entries/save-entry') }} and would like to be able to use this entry immediately upon redirecting from the submit. From the docs I see that the redirectInput() function only accepts a url string. Is it possible to get my hands on the newly created entry's id in order to use it in the redirect?
For context, I have a page with a user-operated form which, when submitted, creates an entry that represents the customer's order. And upon submission I want to immediately head to a review page where it displays the new order's details back to them. Is there a better way to go about this flow? The only thing I can think to do is use a hidden field to set a unique hash on the slug which I also use in the url put in the redirect.

I think the answer is as simple as providing the new Entry's URI to the redirectInput function:
<form method="POST">
  {{ actionInput('entries/save-entry') }}
  {{ redirectInput('{uri}') }}

  <input type="text" name="title">
  <button>Save!</button>
</form>

Craft looks at the string you pass in, and evaluates it as an "object template," wherein you can use the short-hand syntax here ({uri}) to access properties of the saved Entry.

Keep in mind! The behavior here differs based on what Controller you're using—sometimes it'll be a different kind of Element, which may or may not have a useful/predictable uri (i.e. if you're updating an Asset).

The "template" you pass in can be as complex as you want. For example, if the form was part of your dashboard, you might want to prepend with a path of some kind:
{{ redirectInput('my-account/orders/{id}') }}

Similarly, you can use regular Twig syntax here—Craft just does some of these easy substitutions for you:
{{ redirectInput('my-account/orders/{{ object.id }}') }}

Note that the "template" won't get rendered in the actual request, so you'll see exactly what you typed here (well, plus a hash of the string, so users can't manipulate it)—it's only evaluated when submitted.

For more info, check out the redirectToPostedUrl($object) method!


How to do "restricted page/asset"->login->register->"restricted page/asset"? That question will almost certainly need to be rewritten, but at the moment I don't have the language to write it well (sorry).

We have a restricted item (asset, in this case) that successfully triggers the login form and then redirects the viewer to the restricted item after login.

What about if the viewer is not registered yet? We have a working registration form set up and auto-activation enabled. How can the referring restricted item be passed from the login form to the registration form and then have that restricted item shown immediately after registering?

You should be able to get the return url from craft. I just did a quick test and it seemed to carry over to a registration page from a log in page that happened due to a restricted page, so maybe try something like this in your registration template:

{% set redirectUrl = (craft.session.getReturnUrl() ?: '/') %}

<input type="hidden" name="redirect" value="{{ redirectUrl }}">

That way after they register they will be redirected to the restricted page, asked to log in and then craft should redirect them to the restricted page automatically.

Hope that helps!


404 error if folder in public_html has same name as folder in craft/templates I am currently transfering a live website to Craft CMS. I am trying to keep all URLs of pages and images exactly the same as the live version, because of all the pages and images cached in Google. Current URL's are, for example:

http://www.website.com/projects/projectname-1/pictures/picture.jpg

Where projectname-1 and picture.jpg are variable.

In Craft CMS I made a structure called projects. The slug/uri of the entries are setup so that they are the same as the original URL (for example www.website.com/projects/projectname-1)

I made an Asset source with the file system path set as projects/ and asset url as /projects/. When creating an entry within the projects structure, I made it so that when you're adding the images (custom field), it created the subfolder like: projects/{slug}/. The filenames of the images I am uploading are the exact same name as the live version. This all together works, because I am recreating all the same URLs: nice! :)

Now, here comes the problem. I also made a Single for the projects (www.website.com/projects/) page. When I create an index.twig file in craft/templates/projects/index.twig, I get a 404 error when visiting the URL. This is because I also have a folder called projects in my public_html. So, my question is: how do I also show craft/templates/projects/index.twig on my projects Single, while also keeping the original URLs intact (thus at the same time having a /projects/ folder in my public_html).

Hope it makes sense, thanks,

ET

This is because the 'projects' folder exists in both public_html and craft/templates, right?

No this simply means that you have no entry with the slug projects as soon as you create an entry with the given slug it will work.

You can also define a route in a config file

'projects ' => 'projects/index.twig',

Generally your template path structure has nothing to do with your url structure. You should define which template should apply for which url route in your CP in the element settings or via config file or plugin

public function registerSiteRoutes()
{
    return array(
        'projects' => 'projects/index.twig'
    );
}


Import Plugin on localhost Craft 2 crashes I'm using the import plugin by Bob Oldehampsink on a localhost Craft2 site, but, although it appears to have installed successfully, when I attempt to upload the .csv file and click on 'next,' I'm met with a blank screen.
I've checked the format of the .csv and have made various changes, but I still get the blank screen (I only ever see the first screen in the Import plugin).
Thanks for any help or suggestions.

This could be a PHP memory limit issue but it's hard to say until you get access to the log files or can output the error to the browser instead of a blank page.
I would first make sure devMode is enabled in Craft. Then I would look at the log files in storage/logs/web.log or storage/logs/php-errors.log. There might be a lot of stuff logged already, so sometimes it's easier to delete everything in logs and then redo the import and see what errors were logged.


No more Ajax in the control panel after update to Craft 2.7.0 I've update a Craft 2 site to Craft 2.7.0 but since I did no Ajax(?) calls work; I can't clear caches, backup data bases, open a Matrix field,...
Anyone got an idea what went wrong?
Thanks!

Prob solved; I auto updated to Craft 2.7.0 manually, and - stupid me for waiting that long to do that... - I updated it again manually. Problem solved. Case closed


Problem installing plugin via path repository I am starting to play with writing a plugin in Craft 3.0. I have followed the following page. I used Plugin Factory to create my plugin structure (very nice). My folder structure is as follows:

/craft
/craft/vendor/recoveryfinder/nav

I uploaded the files and folders created bt the pluginfactury to /craft/vendor/recoveryfinder/nav folder. My additions to the craft project composer.json look like this:

After:

{
  "name": "craftcms/craft",
  "description": "Craft CMS",

I added:

  "minimum-stability": "dev",
  "prefer-stable": true,

After:

  "scripts": {
    "post-root-package-install": [
      "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
    ],
    "post-create-project-cmd": [
      "@composer dump-autoload -o",
      "@php craft setup/welcome"
    ]
  },

I added:

  "repositories": [
    {
      "type": "path",
      "url": "./vendor/recoveryfinder/nav"
    }
  ]

I went to the terminal logged in as the user that owns the files and change location to:

  /craft

I then ran:

  composer require recoveryfinder/nav

The output I am getting is:

Using version ^0.9.0 for recoveryfinder/nav
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals

  [RuntimeException]
  Package recoveryfinder/nav cannot install to "/home/recoveryfinder/craft/vendor/recoveryfinder/nav" inside its source at "/home/recoveryfinder/craft/
  vendor/recoveryfinder/nav"

require [--dev] [--prefer-source] [--prefer-dist] [--no-progress] [--no-suggest] [--no-update] [--no-scripts] [--update-no-dev] [--update-with-dependencies] [--update-with-all-dependencies] [--ignore-platform-reqs] [--prefer-stable] [--prefer-lowest] [--sort-packages] [-o|--optimize-autoloader] [-a|--classmap-authoritative] [--apcu-autoloader] [--] [<packages>]...

I have not modified in any way the files created by pluginfactory.io.

Any pointers as to what I did wrong?

The article I wrote So You Wanna Make a Craft 3 Plugin? may help you in terms of figuring out how to properly set up a "host" website to run your plugin development from.

TL;DR your repo shouldn't point to your site's vendor directory, it should point to wherever that plugin exists on your local dev environment.


Is it possible to make Craft/Twig throw 404 if a template can't be found? Attempting to include a template that doesn't exist throws HttpStatus 500 – Craft\TemplateLoaderException – Unable to find the template “{template}”.

This is usually fine and what you want, but is it possible to override this behaviour somehow, and make Craft throw a plain' old 404 instead?

Here's one way to do it – not super elegant, but it works:

{% set template %}
    {{- include('sometemplatethatdoesntexist', ignore_missing = true) -}}
{% endset %}

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

{{ template }}


Is it possible to change a loop if mobile browser is detected? I have a loop to go through my products which go in batches because they need to show detail info every third entry. When the Website is viewed from a mobile device, Tablet or Mobile I want it to loop in Batches of 2 instead of 3.

All I get when I make an "if" statement is errors about the for loop not closing.

    {% if craft.request.isMobileBrowser %}
        {% for batch in craft.entries.section('afval')|batch(2) %}
    {% else %}
        {% for batch in craft.entries.section('afval')|batch(3) %}
    {% endif %}
    lots of content here...
    {% endfor %}

So how can I get the loop to go in 2 entries per batch instead of 3 when reached "col-sm"(bootstrap) or atleast when a mobile device is detected.

You should close your for-tag pair within the {% if ... %}.

So:

{% if craft.request.isMobileBrowser %}
    {% for batch in craft.entries.section('afval')|batch(2) %}
        ...
    {% endfor %}
{% else %}
    {% for batch in craft.entries.section('afval')|batch(3) %}
        ...
    {% endfor %}
{% endif %}

Or, even better:

{% set batch = craft.request.isMobileBrowser ? 2 : 3 %}

{% for batch in craft.entries.section('afval') | batch(batch) %}
    ...
{% endfor %}


Craft Commerce 2 - get order data for plugin I want to write a plugin which writes all the order data into a CSV file.
Unfortunately the documentation for Commerce 2 isn't quite complete yet so I have difficulties to find out how to do the following with a plugin (so I need to use PHP and not Twig).

Get an order by ID.
Get ordered items.
Get the addresses for the order.

Every help appreciated.

$order = \craft\commerce\elements\Order::find()->id($id)->one();

if($order)
{
  foreach ($order->getLineItems() as $item) {
   // $item->description
   // $item->qty
  }

  $billingAddress = $order->getBillingAddress();
  $shippingAddress = $order->getShippingAddress();
}


Dynamic postCpLoginRedirect based on user permissions I'm wondering if it's possible to set the postCpLoginRedirect config setting dynamically during plugin initialization. Seems like that's a no-go, but wanted to confirm. Ideally, I'd like to ID users with very limited CP access and direct them straight to their view's url (effectively skipping the dashboard for this user group only). I would welcome suggestions for best-practice workarounds/alternatives if dynamic setting of this property is not possible. Thanks!

You don’t need to dynamically set the postCpLoginRedirect template, you can point to a single, unified template. Once the user has been redirected, make all of your dynamic decisions within the Twig template.
If you want to then choose to redirect to yet another template, just use the Twig redirect tag.


Manual Update 500 error Downloaded latest release, pushed app-new to server, renamed app to app-old, renamed app-new to app.

Try to go to admin, and I get a 500 error.

Server error log shows.
2017-11-15 12:29:29 Error   500 GET /admin HTTP/1.1

Any ideas.
Trying to update an install that hasn't been updated in a long time.
Going from 2.6.2911 to 2.6.2974

I can still get to admin if I use the old app by renaming app to app-new, and app-old to app

Re-downloaded manual update, and pushed to the server via ftp again fixed the issue. Download might have been corrupt is my only thought.


Commerce 2 — Guest checkout error: no customer email address exists on this cart I'm having a problem with checking out as a Guest.

Below is the design so you can see what I'm talking about...

Although I'm entering an email address in the Guest Checkout email field — when I get to the payment page it won't allow payments to process due to an error pop-up message stating "no customer email address exists on this cart."

Both login options (on the Checkout index template) are using separate <form>'s so I know that isn't an issue. I've tried different email addresses and still nothing.

I've also checked the Craft Commerce GitHub repo templates and can see the action and redirects are the same as what I've got in mine.

Has anyone else came across this problem before and knows how to fix it?

Is it worthwhile switching to the new template structure (email > account > etc etc)?

Thanks in advance

Switching to the new template structure fixed the issue I had regarding the email not being recognised/saved.