Worldpay Gateway not redirecting to Customer Order screen on successful transaction I have live site with PayPal payment Gateway and works flawless. Problem appears when I want to use also WorldPay.
Payment is going throught but after payment browser is not redirecting to Order Summary Screen and order doesn't appear as placed order in CP.
I set up everything as stated in Craft Commerce doc. I really don't know what I can do else :(

Orders only appears in ACTIVE CARTwith status REDIRECT.

Another order is adding to the same order that's the problem to identify what has been bought.

Are you testing from a local domain or on a remotely accessible server?

If it is a local domain then the return cannot work since Worldpay doesn't know where 'local' is.

If this is a remote server then:

Is the site turned 'on'? i.e. do you need to be logged in to view the front end
Do you have http auth in place (for instance to stop robots crawling a staging site).

If either of the above is true then it's likely that Worldpay can't get to the site.

Finally, do you have CSRF protection turned on? Try turning it off. If that solves the problem then you will need to bypass it in some way in order for Worldpay to work.


Adding entries to the top level scope of a variable in Twig I have made a frontpage editing system where the user can desk a frontpage, adding news items and other blocks manually. One of the blocks is "Last n news items". I would like this to include the last added news posts, except the ones that are already added manually.
I create an array called shownNews and add items to it each time the "show news item" block is called. My problem is probably related to variable scoping, the array is updated locally, but not in the global page scope.
{% set shownNews = [] %}

    {% for block in entry.layout.all() %}
        {% include '_blocks/' ~  block.type %}
    {% endfor %}

And then inside the included block I call
{% set entry = block.article.one() %}
{% set shownNews = shownNews|merge([entry.id]) %}

If I output the shownNews variable at this point inside the block it has correcly added the id to the array, but it is not available to the next block that is called.
I believed that if I declared the array on the top level it would be available for the included blocks both for reading (which works) and writing (which doesn't). What am I doing wrong here?

I'm working on solving a similar problem and I've come up with a solution that stores a string of comma-delimited IDs in the session like this:
{% set displayedContentIds = craft.app.session.get('displayedContentIds')|split(',') %}

This code is added to all components on the page that are required to exclude content that's already been shown further up the page. I pass the array of IDs to the entry query for that block, if there are IDs to exclude:
{% set criteria = {
    section: 'mySection',
    limit: 5
} %}

{% if displayedContentIds|length > 0 %}
    {% set criteria = criteria|merge({ id: 'and, ' ~ displayedContentIds|join(', not') }) %}
{% endif %}

{% set entries = craft.entries(criteria) %}

I output my entries as normal with entries.all(), then I update displayedContentIds with the just-displayed entry IDs:
{% set displayedContentIds = "#{displayedContentIds},#{entries.ids()|join(',')}" %}
{% do craft.app.session.set('displayedContentIds', displayedContentIds) %}

This is a bit crude if I'm honest, but it's the only way I can think of to update a variable inside a block and have the updated value available to blocks further down the page.


Activate account email {{link}} Looking at the possibility of sending the link in account activation emails to a set page rather than the homepage which {{link}} does so we have:

http://domain.net but they go to http://domain.net/welcome

Thanks
Simon

OK, just did a quick look through the docs. Appears that this can be set via the config file.

Link to documentation

There's also the option to set whether the user is logged in automatically.


Math with numeric values derived from a dropdown field I had a dropdown field with a handle of hLevel, with only numeric values in it, anticipating that I could do math with the values in my template. But it seems I can't.

{% set dif = subhead.hLevel - subhead.next.hLevel %}

…returns an error message ending in:

  “could not be converted to int”

I found a thread convinced that number_format “converts a string to a number”, so I tried that:

{% set dif = subhead.hLevel|number_format - subhead.next.hLevel|number_format %}

…but that doesn't work either. The error message changes to:

  “could not be converted to double”

Which doesn't surprise me as I did think that number_format is for float to formatted string conversion, not the other way round as well.  ¯\_(ツ)_/¯

When I change the field format to number everything works fine, but…

It would be good if there is an option to have dropdown field values be parsed as numbers, because from a UX perspective I would prefer that the field is a dropdown.

Or is there some workaround I've missed?


Conditional Parsing Issues I'm not sure what's wrong with this original markup:

Conditional One (doesn't work)

{% if entry.metaTitle is defined %}
  {{ entry.metaTitle }}
{% elseif title is defined %}
  {{ title }}
{% else %}
  {{ siteName }}
{% endif %}

This works but seems a bit much for some simple checks:

Conditional Two (does work)

{% if entry.metaTitle is defined %}
  {{ entry.metaTitle }}
{% endif %}
{% if (title is defined) and (entry.metaTitle is empty) %}
  {{ title }}
{% endif %}
{% if (title is empty) and (entry.metaTitle is empty) %}
  {{ siteName }}
{% endif %}

As you can see I'm checking first if metaTitle is set, then title then finally fallback to siteName. Entering data for the first two return results, but not sure why if metaTitle and title are empty why siteName doesn't return in the first conditional

#

Update based on Aaron's answer:

Tried this too:

{% if (entry.metaTitle is defined) and (entry.metaTitle is empty)  %}
  {{ entry.metaTitle }}
{% elseif title is defined %}
  {{ title }}
{% else %}
  {{ siteName }}
{% endif %}

#

Also tried this, Aaron was missing a ( in his answer :)

{% if (entry.metaTitle is defined) and (entry.metaTitle != '')  %}
  {{ entry.metaTitle }}
{% elseif title is defined %}
  {{ title }}
{% else %}
  {{ siteName }}
{% endif %}

But that doesn't work either with the same initial results.

This looks like a situation where you might get away with just using Twig's default filter:

{{ entry.metaTitle|default(title|default(siteName)) }}

It works even with undefined or empty strings, and methods that don't exist on objects that might not be defined themselves.


FeedMe plugin multi language import I would like to import data for fields with multiple locales with the FeedMe plugin. I have to create the JSON feed, so how can I do that? Thanks for your help!

I found out, what my mistake was: If you import only one locale the fields must not be mandatory, otherwise you get an error about fields (the ones in the other locale) being empty.


id: 'not' with variable i think the following code shows the problem:

{% for entry in craft.entries({ section: 'news', limit: 2, **id: not this_id** }) %}

the big one doesn't work in this way. Has anyone an idea?

The content of this_id is a number.

Thank you!

It should be a string:

{% for entry in craft.entries({ section: 'news', limit: 2, id: 'not 42' }) %}

so concat your variable like so:

{% for entry in craft.entries({ section: 'news', limit: 2, id: 'not ' ~ this_id }) %}


302 redirects to locales in main index.php I have written this simple redirect code in the main index.php file.
Now I need to know if this code can somehow cause problems with Craft:

    // Check if URI contains cpTrigger
    $pos = strpos($_SERVER['REQUEST_URI'], 'admin');

    if ($pos === false) {

        // Language paths
        $paths = array(
            'de'=>'/de/',
            'it'=>'/it/',
            'en'=>'/en/'
        );

        // Browser language
        $language = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);

        // Default language
        if (!isset($paths[$language])) {
            $language = 'de';
        }

        // Redirect
        header('HTTP/1.1 301 Moved Permanently');
        header('Location:' . $paths[$language]);

    } else {

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

        // Do not edit below this line
        $path = rtrim($craftPath, '/').'/app/index.php';

        if (!is_file($path)) {
            exit('Temporary error. Could not find the CMS folder.');
        }

        require_once $path;

    }

Only the 404 page doesn't load with www.example.com/idontexist but loads instead the homepage.
(www.example.com/en/idontexist loads as expected the 404 page)

Perhaps somebody knows a better solution?

I would suggest making the “admin” check a little more strict:

// Make sure this isn't a CP request
if (!isset($_GET['p']) || strncmp($_GET['p'], 'admin', 5) !== 0)
{
    // ...

(Assuming you’re using the recommended .htaccess redirect rule, by the time the request hits index.php, the original request URI will be available as $_GET['p'].)

The Accept-Language header can actually include multiple languages, so you might want to consider looking at all of them, sorted by weight. HttpRequestService::getBrowserLanguages() has some example code on how to do that.

A 302 redirect would probably be more appropriate than 301. You wouldn’t want Google to think that http://example.com/ should always really be http://example.com/en/ or whatever this script might end up sending it to, and people could theoretically change their browser’s language preferences.

You also might want to include $_GET['p'] in your redirect location. Right now you’re just sending all traffic off to the locale-specific homepage, which is why 404s aren’t working as expected.

To put it all together, here’s what you might want to do:

<?php

// Make sure this isn't a CP request
if (!isset($_GET['p']) || strncmp($_GET['p'], 'admin', 5) !== 0)
{
    // Language paths
    $paths = array(
        'de' => '/de/',
        'it' => '/it/',
        'en' => '/en/'
    );

    // Get the browser's preferred languages
    if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && preg_match_all('/([\w\-_]+)\s*(?:;\s*q\s*=\s*(\d*\.\d*))?/', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches, PREG_SET_ORDER))
    {
        $languages = array();
        $weights = array();

        foreach ($matches as $match)
        {
            $languages[] = strtolower(substr($match[1], 0, 2));
            $weights[] = !empty($match[2]) ? floatval($match[2]) : 1;
        }

        // Sort the languages by their weight
        array_multisort($weights, SORT_NUMERIC, SORT_DESC, $languages);

        // Find the first match
        foreach ($languages as $language)
        {
            if (isset($paths[$language]))
            {
                $matchingLanguage = $language;
                break;
            }
        }
    }

    // Default to German
    if (!isset($matchingLanguage))
    {
        $matchingLanguage = 'de';
    }

    // Redirect
    $url = $paths[$matchingLanguage].(isset($_GET['p']) ? $_GET['p'] : '');
    header('Location: '.$url, true, 301);
}
else
{
    // Path to your craft/ folder
    $craftPath = '../craft';

    // Do not edit below this line
    $path = rtrim($craftPath, '/').'/app/index.php';

    if (!is_file($path))
    {
        exit('Temporary error. Could not find the CMS folder.');
    }

    require_once $path;
}


Total sum within loop I have simple loop:

{% for total in thing %}
  {{ total.seatsKids }} {{ total.seatsParents }}
{% endfor %}

This results in a string of numbers eg. 1 3 4. I want the sum of all numbers. So how do I get 7 at the end? I don't understand how to write math operations within loops.

To do math in twig, you will need to use the set tag to do assignments, and the + operator to do addition. When doing math inside a for loop, you will need to keep in mind that

  loops are scoped in Twig; therefore a variable declared inside a for loop is not accessible outside the loop itself.
  If you want to access the variable, just declare it before the loop.

It looks as if you have a collection of things that represent seat counts, and you want to loop over them and calculate the totals. So, something like this:

{# define and intialize our variables outside the loop #}
{% set kidSeatTotal = 0 %}
{% set parentSeatTotal = 0 %}

{# loop over the seatCounts and add them up #}
{% for seatCount in thing %}
  {% set kidSeatTotal = kidSeatTotal + seatCount.seatsKids %}
  {% set parentSeatTotal = parentSeatTotal + seatCount.seatsParents %}
{% endfor %}

{# maybe we want the grand total as well #}
{% set grandSeatTotal = kidSeatTotal + parentSeatTotal %}

{# now we can output them: #}
kid seat total: {{ kidSeatTotal }}
parent seat total: {{ parentSeatTotal }}
grand total: {{ grandSeatTotal }}


Order "Entries Fields" by entry order I want to order entries in an "Entries field" by the order I added them to the field. So Anastasia would be first and Beni would be last.

My only idea was .fixedOrder like you would do it with an asset field:

{% for entry in craft.entries.section('musiker').relatedTo(entry).fixedOrder(true) %}
   {{ entry.name }}
{% endfor %}

But that does nothing.

It's order('sortOrder') instead of fixedOrder(true).

{% set entries = craft.entries({
    relatedTo: { sourceElement: entry, field: 'entriesFieldHandle' },
    order: 'sortOrder',
    limit: null
}) %}

If you don't make any further modifications to the params (i.e. reverse order, other limit) there's also the short syntax for the above that Jamie already suggested:

{% set entries = entry. entriesFieldHandle %}


Can you use Routes on Structure entries I'm using a route to use a different template, but whatever I try the page remains unchanged, my structure is set as:

entry url format: {slug}

entry template: _pages/_entry

I want an entry's slug to use a different template - would this possibly be affecting the route being followed?

I want the entry 'home' to use the 'index' template (and not the '_home' template which exists at _pages/_home)

I've cleared my cache and updated indexes

You know you can do things like this in your root entry  template to load it dynamically based on slug or entry type

{% extends [
  'pages/_custom/' ~ page.slug ~ '.twig',
  'pages/_entrytypes/' ~ page.type ~ '.twig',
  'pages/_generic.twig' ]
%}


Is there an event that is triggered when an entry expires? I would like to update an entry after it has expired via a plugin. Is there an event that I can use to do this when using Craft 2?

There is no event for this and it would not be possible via event since no one is executing any scripts. Unless there is a request there is no way for PHP to execute code on its own so you need to create a cronjob or a Craft task and execute your functions when someone visits the site.

I would create a cronjob that executes hourly and search for expired entries in order to find them. You can store a value in a field that is not in the layout of the model to mark it as "handled"


Craft 3 - ajax request to plugin This is a pretty simple test before I implement some larger functionality. Eventually this will be just a glorified upload form via ajax.

Part 1 - Ajax post

$.ajax({
    type: 'POST',
    url: '/upload2',
    dataType: "json",
    data: JSON.stringify({"abc": "123", csrfTokenName: csrfTokenValue}),
    success: function(data, textStatus){
        alert('form submitted successfully');
        alert('data'+data);
    },
    error: function (data, ErrorText, thrownError) {
        console.log("Failed to process request correctly, please try again");
        console.log(data);
    }
});

Part 2 - Plugin

Plugin is installed. Inside my plugin init I've got a site rule setup:

$event->rules['upload2'] = 'plugin/default/upload';

I can visit this url in the browser without issue. Here's my function I'm trying to access:

public function actionUpload()
{
    $response_array['status'] = 'success';
    $response_array['post'] = $_POST;
    return json_encode($response_array);
}

When I try and run said code via ajax, console returns Bad Request: Unable to verify your data submission. and a 400 (Bad Request) error to boot.

This could easily be one of those doh! moments but so far I'm losing this war. Should I just quit the internet and go live in the woods? (kidding)

Anyone have any idea what I'm doing wrong here? Are ajax posts different in Craft 3?

95% of the time you see a 400 Bad Request error, it's because it's a CSRF token validation error (or you're just missing the token all-together).

Craft 3 has CSRF validation enabled by default.

Here's how to pass the CSRF token to your JS in Craft 2: https://craftcms.com/support/csrf-protection#updating-your-javascript

Here's the CSRF token changes in Craft 3 you'll need to change: https://docs.craftcms.com/v3/changes-in-craft-3.html#csrf-token-params


Disabled entries showing up On the following screenshot the image on the right called Crown Wood - Plot 1 is disabled in the CMS, so I'd like it not to show up in the results.

Below is my code. I added .status('live') to the for loop as suggested elsewhere in the forum but the disabled posts are still showing up.

Can someone help, as I only want the section to show live entries.

{% set var = craft.entries.positionedAfter(entry).level('2') %}
{% for entry in var.limit('5').status('live') %}

      {% if entry.plotGallery.first() %}

      {% endif %}

{{ entry.parent ? entry.parent.title }} - {{ entry.title }}

{% endfor %}

The code is correct, it was that I hadn't disabled the individual entries in the CMS, I'd only disabled the parent in the structure.

So adding .status('live') on the end of the for loop is the solution, and making sure every entry at all levels is disabled.


How do I add a block to a matrix that already has content via a plugin? I'm building a plugin that adds blocks to a matrix in an entry from the front end. I got it up and running by following the answer in this post:

How to save a matrix content of a new entry in my plugin?

How do I check if the matrix already has blocks when I fetch the entry? And then, once I know if the matrix already has blocks, how do I retain the existing data while saving new blocks via the plugin?

You can save Matrix blocks directly, without having to re-save the entry.

Craft 2

Use MatrixService::saveBlock():

$block = new MatrixBlockModel();
$block->fieldId = 5;
$block->ownerId = 100;
$block->ownerLocale = 'en_us';
$block->typeId = 2;
$block->sortOrder = 10;

$block->setContentFromPost(array(
    'fieldHandle' => 'value',
    // ...
));

$success = craft()->matrix->saveBlock($block);

Craft 3

Use craft\services\Elements::saveElement():

use Craft;
use craft\elements\MatrixBlock;

$block = new MatrixBlock();
$block->fieldId = 5;
$block->ownerId = 100;
$block->siteId = 1;
$block->typeId = 2;
$block->sortOrder = 10;

$block->setFieldValues([
    'fieldHandle' => 'value',
    // ...
]);

$success = Craft::$app->elements->saveElement($block);


Element Criteria Model: filtering by empty values I'm trying to use the Element Criteria Model to retrieve all entries where value X or value Y is not null?

I can get all entries where values and X and Y are not empty but not sure how to achieve this with either X or Y being not empty. any thoughts?

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->limit = NULL;

foreach ($fields AS $field) {
    $criteria->$field = ':notempty:';
}

$entries = $criteria->find();

This is what I have for AND but not sure how best to go about achieving the same query for OR.

An equivalent SQL query would be something along lines of WHERE (X IS NOT NULL && X <> '') OR (Y IS NOT NULL && Y <> '')

Okay, doesn't seem to be the most elegant but the only way I could achieve this was by carrying out the entries criteria query within my $fields loop. So, for example:

$entries = [];

foreach ($fields AS $field) {
    $criteria = craft()->elements->getCriteria(ElementType::Entry);
    $criteria->limit = NULL;
    $criteria->$field = ':notempty:';
    $tmpEntries = $criteria->find();

    $entries = array_merge($entries,$tmpEntries);
}


Correct Asset URL when using folders My Craft blog has the path localhost:8888/blog
The Assets are in the folder assets, so its localhost:8888/blog/assets.
I set the path of an image to /assets, but then it looks for an image at localhost:8888/assets. Is there any way to handle this dynamically, without needing to write blog/ in front of every asset url?

I have also found this slightly confusing from time to time. These settings work well for me:

FYI, on the server the path is: .../public_html/uploads/services

Hope it helps


Fetch Image URL from entry CMS This seems like it should be really simple. I set the field for an image asset, linked it to the entry type I want it associated to, and then uploaded the image in the cms to the folder I specified.

So now, when I call {{ entry.featureImage }} it should return the object of that image. I want its URL, because I want to place it in a special image tag. <img class="img-responsive" src="{{ entry.featureImage }}"> Now I know this returns an error that says "Object could not be converted to string". Because I need to modify it to get the string of the URL. How can I do this? I feel like I've tried everything and scoured the docs and internet. I cant just attach a .getURL() or .url like would make a whole ton of sense. I've even set entry.featureImage as a variable and then called image.url on it. Or .getImg('featureImage') maybe? But it needs the class of img-responsive.

This needs to be possible so that the CMS can allow for images to be specified and uploaded for specific spots in the website.

I bet this trips up a lot of people at first, but your asset field will return a ElementCriteriaModel, not your image.

To get to image, you need to fetch it. If your field has only one image, you will do something like this:

{# Fetches the first image #}
{% set image = entry.featureImage.first() %}
{# It's good to check if you actually have an image before trying to get the url #}
{% if image %}
    {{ image.url }}
    {# Or alternatively #}
    {{ image.getUrl() }}
    {# If you want to get a specific transform: #}
    {{ image.getUrl('transformHandle') }}
{% endif %}

The Assets fields documentation got some good examples on the different use cases.


Craft 2.6 Session Issues We are having issues staying logged in to Craft (2.6). There was a plugin error which is what we thought was causing the issues, so we removed the sprout SEO plugin. However the error still persists. We keep getting kicked out, and sometimes the words 'unkown error' pop up. We have not bee able to load any new content due to this.

Please may you assist us urgently.

Thanks you so much,
Ashton

There are several reasons (mostly environmental) why a person would be logged out from the CP discussed in these posts (along with fixes/workarounds):

Craft constantly logging out from admin area

Migrated Server, Now Getting Logged Out Constantly

Keep on getting logged out when deploying using Capistano

Users are always logged out on front end

Load Balancing Craft CMS - Admin gets logged out instantly

I'd start by reviewing those.

  and sometimes the words 'unknown error' pop up.

My hunch is it's related to your session issues, but you can check your craft/storage/runtime/logs folder for the underlying error message.

Also related and may be helpful:

The Case of the Missing PHP Session


How to debug a payment gateway error I created a payment gateway for Commerce 2. When I try to make a payment, an error happens and the flash error I get is this "Invalid payment or order. Please review.".
I don't know if my gateway is returning the error or Craft.
How do I know what is the error especifically?

On the Transactions tab of the order, there should be a payment attempt with a failed status. There's a small information icon which returns the gateway response.


How do you template an IF statement to avoid an error if an image is not assigned Here is my templating...

      {% if entry.programImage %}
        <img src="{{ entry.programImage.one().getUrl() }}" alt=""/>
      {% endif %}

The field programImage is NOT required.

The image does display for entries that have it.
It throws an ERROR for those that do not.

The ERROR message is as follows.

Impossible to invoke a method ("getUrl") on a null variable.

What am I missing?

Thanks

You're close...

{% set programImage = entry.programImage.one() %}
{% if programImage %}
    <img src="{{ programImage.getUrl() }}" alt=""/>
{% endif %}

You get the the asset model (or null), then check if you actually have it, then finally use it.

It's essentially the same in Craft 2.


Listing all entries in one section related to entries written by currentUser in another section The setup:

Section A (entries I want to list)

Section B

entries field (related to 1 entry from SectionA)

My goal is to list all entries from Section A, that are related to an entry in Section B  authored by the currentUser.

Right now what I'm doing is looping through all entries in Section B authored by the current user and querying/displaying the entry related to it, but it's way too inefficient and eats up a lot of database queries. Was hoping there's a more efficient way of doing this.

Not sure whether or not there's a way to achieve this sort of relation via a complex relatedTo or if I need to go another route.

Can provide additional information/clarification if anything is unclear.

Thanks

I think this is what you mean:

{% set sectionBEntries = craft.entries.section('B').authorId(currentUser.id) %}

{# 'relatedTo' works both ways, so we can use sectionBEntries
    as input for relatedTo to get all section A entries that have
    a relation to one of the section B entries by currentUser #}
{% set sectionAEntries = craft.entries.section('A').relatedTo(sectionBEntries) %}

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


Can I disable logging 404 errors in my craft.log file? I want to get a better understanding of some issues in production surrounding timeouts but as its a high traffic site the craft logs get replaced about every 15 minutes due to the amount of 404's that are requested.

Most are stuff like missing apple-touch-icons or old images from our last version of the site that are now gone. Is there any way to tell craft either to not log those 404s so that craft.log becomes a little more useful?

Not currently, but I agree it's kind of annoying.

I thought maybe you could pull it off with a plugin since Yii does have an onException event, but there wouldn't be a way to disable logging of 404's without some code changes on our end.

I've added it to our 3.0 list to add a config setting to disable logging of 404's though.


Is it possible to add white background to transformed images? For a client eCommerce project I am working on all the product images are on white backgrounds, so they blend nicely with the background of the site. Currently I am putting all the images through a fit transform (480px by 480px), so that parts of the image aren't cut off.

The images are of different shapes and sizes and are transformed something like this (the grey area is the actual visible product part of the image)

However, I am trying to achieve something like this, so all the images are 480px by 480px, and the visible content is slap bang in the middle. Anything extra is added as whitespace to make all the images the same dimensions.

Is this something Craft can do and I am just being a dolt?

Update

At the risk of this question being closed as off topic, please note that I am not looking for a CSS/JS related answer for this.

I'm trying to find out if there is a way Craft can process the images for me, perhaps with ImageMagick or something similar to achieve what I am hoping for.

Unless one of the devs say otherwise, Craft's image processing is resizing only. They do not add anything to the image.


How to import entries from Craft 2 to Craft 3? So, I've been working on a Craft 3 upgrade, managed to set everything up, including configuring new plugins etc. Since I've started working on the upgrade process, some new entries have been published on the original site (running on Craft 2).

What's the best way to import only the blog entries from the latest database dump? I tried to replace the craft_content table in the database, but that doesn't seem to work well - I assume the table structure is different on Craft 3?

Is there maybe any plugin for doing such thing?

I also thought of getting the fresh DB dump from the live site, converting it to Craft 3 and then replacing the craft_content table, but I'm not convinced if that's the best way to do it.

Or maybe I should replace some other tables too? Couldn't find any DB description in Craft documentation.

Thank you.

The typical way to do this would be to use something like https://plugins.craftcms.com/feed-me, where you could setup a feed of the data you want to export, map it to the proper fields in Craft 3, then import the data from a feed.


Locked out of admin panel after update I updated a very old Craft installation (v2.6.2794 to v2.6.2971) and now I'm locked out off the admin area. I can get to the login panel and log in but once in I just get 500 errors.

After turning on devMode, I found this:

Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 72 bytes) in /mysite.com/craft/app/helpers/ModelHelper.php on line 102

I already have my phpMaxMemoryLimit at 512M (checked). Could my installation really be using that much memory?

I'd initially forgotten to turn on devMode to find out what the 500 error was. Once I did that I found out it was exhausting the memory. I had to raise it up to 1024M!


Hidden files are no longer accessible with AJAX in Craft 3 I'm not sure if this is a bug, a security feature, or something to do with Twig 2; but since Craft 3 (RC3) I'm no longer able to access hidden twig files via ajax.

This works fine:

  $.ajax({
    method:'GET',
    url:'/blog/test',
    success:function(data){
      $('body').append(data);
      console.log("SUCCESS", data);
    },
    error:function(data){
      console.log("ERROR", data);
    }
  });

However, when I point the url to a hidden file with this:

url:'/blog/_test',

I get a 404 (Not Found) error. For my example, I have both '_test.twig' and 'test.twig' files in the 'blog' directory.

Am I missing a breaking change?

Update:

I didn't really know what it was for, but 'enableCsrfProtection' => true has always been set in my config/general.php file. (In both Craft 2 and 3). I've tried setting this to false too, and I'm getting the same results.

Following Robins comment, I've attempted to follow these instructions: Enabling CSRF Protection.

I've set the global variables window.csrfTokenName and window.csrfTokenValue. And now I'm stuck.

I'm pretty new to ajax, and I'm not sure how to extrapolate the example in a way where I can add the CSRF Token correctly in my 'GET' method.

This is the response I'm getting:

ERROR
{readyState: 4, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …}
abort : (statusText)
always : ()
catch : (fn)
done : ()
fail : ()
getAllResponseHeaders : ()
getResponseHeader : (key)
overrideMimeType : (type)
pipe : ()
progress : ()
promise : (obj)
readyState : 4
responseText : "
Not Found: Page not found.
"
setRequestHeader : (name,value)
state : ()
status : 404
statusCode : (map)
statusText : "Not Found"
then : (onFulfilled,onRejected,onProgress)
__proto__ : Object

My guess is still: you did not define a route correct route for your template. You can check if you can access the file when you call the route normally via url www.example.com/blog/test if you can see the template, then it should usually work, if not you did not define any routing rules see here

However: when you do it that way everyone with the link may see this template and I expect it to look not very good without content since it's probably only a partial, so I would highly recommend you to use the proper way via controller.

public function actionRenderTemplate(){
    $response = [
        'success'   => false,
        'message'   => 'something went wrong'
    ];
    if($template = Craft::$app->getRequest()->getBodyParam('template')){
        try{
            $response['success'] = true;
            $response['html'] = Craft::$app->getView()->renderTemplate($template, [
                'foo' => Craft::$app->getRequest()->getBodyParam('just an example to pass values');
            ]);
        }catch(\Twig_Error_Loader $e){
            $response['message'] = $e->getMessage();
        }catch(\yii\base\Exception $e){
            $response['message'] = $e->getMessage();
        }
    }
    return $this->asJson($response);
}

And your javascript

$.ajax({
    type: "post",
    data: {
        action: 'plugin-handle/controller/render-template',
        template: 'path/to/template'
    },
    url: '',
    success: function (data) {
        if (data.success === true) {
            // do your stuff
            $('body').append(data.html);
        } else {
            // something went wrong
            // show a message or whatever
        }
    }
});

Edit
Please make sure you are in the correct folder for rendering your template, there is a difference between frontend and cp requests docs that's why we always build a custom template service that checks if there is a template in the normal path first and only takes the plugin template if there is none so we can overwrite plugin templates if needed and don't need to check/overwrite the paths every time


Covering both "www.domain.com" and "domain.com" in config file settings How can I cover both "www.domain.com" and "domain.com" with the same settings in my config file? My current file is set up like this:

return array(
    '*' => array(
       // Settings here
    ),

    // Local
    'domain.dev' => array(
       // Settings here
    ),

    // Staging
    'staging.domain.com' => array(
        // Settings here
    ),

    // Production
    'www.domain.com' => array(
       // Settings here
    )
);

Can I just remove the www from the last entry under “Production” to have those settings apply to both the naked domain and the www subdomain?

And if I'm including the www in my siteUrl config setting in Production, will that create any conflicts if visitors end up at a naked url without the www subdomain specified?

Thanks!

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

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

Then in the config file:

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

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

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


Possible to filter an entry based on property? Trying to pull in a limit of 2 events that are upcoming (so the event's eventDate should be newer than today). I currently have this:

{% set entries = craft.entries.section('events').order('eventDate asc') %}
{% set today = now|date('Y-m-d') %}

{% for event in entries %}
  {% if today <= event.eventDate %}
    <!-- markup here -->
  {% endif %}
{% endfor %}

However, this returns all events that are upcoming. I would like to only limit it to 2. The problem when I put the .limit(2) on my for loop is that it chooses the first two (and those happen to be older events). Do I need to do another loop within the if statement and add .limit(2) to that or is there a better way?

Thanks!

This should work below. Rather than querying all entries and looping through, just select the entries you need (ie. now) and limit them.

{% set upcomingEvents = craft.entries.section('events').eventDate('>= '~now).limit(2) %}
{% for event in upcomingEvents %}
    <!-- markup here -->
{% endfor %}


Paginate based on items in a Category I'm trying to wrap my head around Pagination in Craft. I have a template that outputs a list of products based on the Category that is passed to it from this thread:
{# Fetch the entries related to auto-injected category variable #}
{% set entries = craft.entries()
    .section('mySection')
    .relatedTo(category)
    .all()%}

{% for entry in entries %}

{{entry.title}}

{% endfor %}

It works great, but I need to paginate it. I'm new to Craft so I'm sure I'm missing something simple, but all the examples I've seen, plus the docs, show how to paginate based on all the entries in a section, but that's doesn't work for me here. Also, the examples seem to conflict with my code, in so far as they are using 'set entries' to get the pagination working, but I'm using it already to get every item from a category. As I said, newbie here so I'm sure I'm missing something simple; any help appreciated.
I'm also hoping I can generate a numeric pagination, but at the moment I'd settle for understanding how to get the basics working in my category example.

You're not far away by combining what you already have with the example in the docs! You just need to pass in the category (.relatedTo(category)) and number of entries (.limit(10)) to show on each page.
{% set query = craft.entries()
    .section('mySection')
    .relatedTo(category)
    .limit(10)
%}

{% paginate query as pageInfo, pageEntries %}

{% for entry in pageEntries %}

{{entry.title}}

{% endfor %}

{% if pageInfo.prevUrl %}Previous Page{% endif %}
{% if pageInfo.nextUrl %}Next Page{% endif %}


What files need to be moved for Craft3 plugins? I'm trying to get the redactor onto my site. I've successfully moved over plugins from the store and a custom plugin I created. But I did those towards the start and had migrated the entire project onto the site. I don't want to move 4,000 files over just to get one plugin to show up.

I've tried moving composer.json, composer.lock, and manually moving the specific vendor folder in as well. I also migrated the database from the dev site to the production site.

So you're really close; composer.json is a list of packages and their semvers that should be installed. composer.lock has a manifest of what is actually installed.

In order to deploy to production, you just need a step that executes composer install to install what is in the composer.lock file. Check out the Deploying Craft CMS section of this article for a more thorough run-through.


Ordering of ElementCriteriaModel with varying statuses I have a built a little plugin that calls the Twitter API to add new Tweets from a user timeline as entries, so that I can return them in an ElementCriteriaModel request to be integrated with content from other Sections.

I am trying to find out the largest tweet ID currently in the Craft system, where tweet IDs are stored as a text field against an entry, so that the next call to the Twitter API can set the sinceId field to only return tweets newer than the latest one currently stored in Craft.

I am doing this by doing an ElementCriteriaModel call, setting the order parameter to 'tweetId desc' and then attempting to find the first() entry, to retrieve the tweetId from that entry.

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'tweet';
$criteria->order = array('tweetId desc');
$criteria->status = array(BaseElementModel::ENABLED, BaseElementModel::DISABLED, BaseElementModel::ARCHIVED);

$latestTweet = $criteria->first();
$latestTweetId = $latestTweet->tweetID;

However, when I do this, the ordering of the Tweets seems to be affected by the status of the entry. It seems to be returning the tweet with the largest ID with status DISABLED, rather than the largest ID across all stored tweets.

Is this behaviour correct, or is there a better way to do this? I do need to be able to set certain tweets to disabled, if I don't want them shown on the front-end of the site.

Your statuses are incorrect. They would be correct for many elements, but the Entry Element overwrites them to the following:

EntryModel::LIVE
EntryModel::PENDING
EntryModel::EXPIRED
BaseElementModel::DISABLED


Conditional to detect mobile devices with getUserAgent? I want to create a User Agent check. (Yes I know. It is evil.)

So I created an Array. The whole idea is to see if the user agent contains a specific word. This way I hope to circumvent regex trickery. But I have a hard time figuring how to return true only once:

This would be the array:

{% set browserValues = [ { agent: 'android'}, { agent: 'iemobile'} {# and so on #}]

This is how I get the user agent:

{% set userAgent = craft.request.getUserAgent()|lower %}

I came this far:

 {% for item in browserValues %}
   {% if item.agent in userAgent %}
     You're on mobile
   {% else %}
     You're not on mobile
   {% endif %}
 {% endfor %}

This actually works. But there are two problems: If the conditional is false (not on mobile), the conditional is applied for each key in the array. You're not on mobile You're not on mobile You're not on mobile

If the user agent string contains the word android twice the conditional is applied twice.

How can I prevent the conditional from looping over and over? (My brain starts to loop over and over too).

Thank you.

Unlike in PHP, it's not actually possible to break a for loop in Twig.

To work around that fact, you can use the for loop to set a flag, and then put the conditional outside the loop:

{% set isUserOnMobile = false %}

{% for item in browserValues %}
    {% set isUserOnMobile = not isUserOnMobile ? item.agent in userAgent : isUserOnMobile %}
{% endfor %}

{% if isUserOnMobile %}
    You're on mobile
{% else %}
    You're not on mobile
{% endif %}

Another option: I actually wrote a plugin called Detect for device detection (the plugin wraps the excellent Mobile_Detect library, which is sponsored by BrowserStack). Might be you'll be be able to use that, instead of hard coding lots of user agent strings. Here's how you can use Detect in a template:

{% set isUserMobile = craft.detect.isMobile %}
{% set isUserTablet = craft.detect.isTablet %}
{% set isUserPhone = craft.detect.isPhone %}
{% set isUserIphone = craft.detect.is('iphone') %}
{% set userAgent = craft.detect.getUserAgent %}


How can I prevent "spam" user registrations? We recently launched our first site with front end user registration and we are getting a lot (not a ton, like 5 a day) spam registrations. See here:

Im trying to find a way to cut down on these without doing something like a captcha but maybe thats my only option?

Plugins:

Snaptcha (private beta)
Works with the User Registration Form, Contact Form Plugin and Sprout Forms Plugin
Invisible Captcha (private beta)

.

Config:

If you don't mind having a few spam-users in your list. Just add purgePendingUsersDuration to your config.

This will purge all users which haven't been activated for x time.


Craft 3: how can I auto-redirect to a site version using the user IP? I have set up multi-sites using several locales:

— International Website
    — English
— Local Website
    — French
    — Dutch
    — etc.

If the user has a French or Dutch IP, it should be auto-redirect to the Local Website version. Otherwise, it should be redirected to International Website.

I found this plugin, that probably could make this works: https://github.com/lukeyouell/craft3-geocookie. I guess I would need to check the cookie inside my base.twig layout before to finally {% redirect %} to the matching version?

But I was wondering if there were (better) other ways to do that?

Thanks!

Country Redirect will let you do that without any latency from external services, with the soon-to-be-released Craft 3 version (I'll update the answer once its out).


query on Super Table field's date field I have a section (events) with a Super Table field that has a date field. I am looking for a way to make a request to have the events superior to now. I cannot find how to do it. The event have multiple dates. Thanks for your help.

It's basically the same as Find entries that use a specific block in their Matrix field?

You can use the base query and left join your Super Table content row

{% set entries = craft
    .entries()
    .section(['your-section'])
    .leftJoin('{{%supertableblocks}} as supertableblocks', '[[supertableblocks.ownerId]] = [[entries.id]]')
    .leftJoin('{{%stc_content}} as stc_content', '[[stc_content.elementId]] = [[supertableblocks.id]]')
    .andWhere(['>=', 'stc_content.field_date', entry.date|date('atom')])
    .groupBy('supertableblocks.ownerId')
    .all()
%}

Note: this is untested, maybe you need certain modifications it should just be some kind of guidance. Please keep in mind to replace your actual table and field names. I just used stc_content as a demonstration as well as stc_content.field_date


Using Services to get all the Categories related to an Entry? In a plugin, I've been advised to try to use craft built-in services instead of direct db queries. So can anyone help with this:  For an entry type that includes a categories field, how to get all the categories related to an entry?

I found this:

$entry = craft()->entries->getEntryById($entryId);

So I suppose this might work as well:

$category = craft()->categories->getCategoryById($categoryId);

But I can't find anything intelligible to me under the relations service.

Thanks for any help.

EDIT: On a related note, I see here that in twig you can do this:

{% for entry in craft.entries.section('news').limit(10) %}

{{ entry.title }}

    {{ entry.summary }}
    Continue reading

{% endfor %}

Whereby Craft/Twig does all the work to find and return the 'summary' field related to each entry. Is there any php statement like this next confused one, following which I could get the categories related to each event?

$events = craft()->entries.section('events').start('<=$toDateYmd').end('OR', '>=$fromDateYmd', '').status('publish');
foreach ($events as $event)
   $categories = $event.category;

Thank you!

If you have an EntryModel and know the category field's handle, you don't really need a service:

$categories = $entry->categoryFieldHandle;

In other cases, you can construct an ElementCriteriaModel to search for related elements (categories, entries, users or assets), using a number of different variables. Easy example to get related categories from an entry ID:

$criteria = craft()->elements->getCriteria(ElementType::Category);
$criteria->relatedTo = array($entryId);
$categories = craft()->elements->findElements($criteria);


Reorder Control Panel Navigation Just wondering there is current any way to control the order of navigation items in the Control Panel. Obviously not a deal-breaker, but was just interested in being ultra-crafty in my Control Panel layout for clients :)

Thanks to the P&T team and the latests update to Craft (2.3.2640), this is now possible through a plugin! https://github.com/engram-design/CPNav


Set fields from two different Matrix blocks, merge them and then set the output in a pretty way Newbie here, still grappling with basics, let alone elegance. My aim is to pull content from four different fields held in two different Matrix blocks and pass the output in a nice human readable format to populate the meta-description tag in my layouts and elsewhere later on the entry page.
I'm getting close but still no beer. I'm having trouble with merging everything. Only one or the other MatrixHandles outputs the correct content:
{# Fetch MatrixBlock fields content for artistName and birthDeathLocationDate #}
{% set artistNameQuery = craft.matrixBlocks()
    .owner(entry)
    .field('artistNameBirthDeath')
    .type('artist') %}

{# Fetch MatrixBlock fields content for materials and dimensions #}
{% set artworkMaterialsQuery = craft.matrixBlocks()
    .owner(entry)
    .field('artworkDateMatDim')
    .type('artworkDetails') %}

{# Try to merge the two above queries, with some merge voodoo #}
{% set artNameMat = artistNameQuery|merge(artworkMaterialsQuery) %}

{# Don't know why but this helps trigger the below, and sends it to my base.twig layout tmp #}
{% set metaDescribe = '' %}

{# Print all of the above into a pretty, human/machine readable format for re-use in base.twig or elsewhere #}
{% for block in artNameMat %}
    {% set metaDescribe = block.artistName ~ ' ' ~ '(' ~ block.birthDeathLocationDate ~ ')' ~ ' ' ~ block.materials ~ ' ' ~  block.dimensions  %}
{% endfor %}

And then over in my base.twig template I've got:
<meta name="description" content="
{% if metaDescribe is defined %}{{ metaDescribe }}{% else %} no meta desc {% endif %}" />

So far it's outputting only the artistNameQuery. If I edit my not totally working merge line to just {% set artNameMat = artworkMaterialsQuery %}, it too sends the correct content for that Matrix handle/block to my base.twig.
Other notes. The above code is written within the template for displaying single artists' artwork (entry), outside of the {% block main %}. Running Craft 3.5.11.1.
Any pointers would be much appreciated!
Update:
I just tried making it all a lot more cleaner  / elegant replacing this:
{% set artistNameQuery = craft.matrixBlocks()
    .owner(entry)
    .field('artistNameBirthDeath')
    .type('artist') %}

{% set artworkMaterialsQuery = craft.matrixBlocks()
    .owner(entry)
    .field('artworkDateMatDim')
    .type('artworkDetails') %}

With this:
{% set artNameMat = entry.artistNameBirthDeath.type('artist').all()
    |merge(entry.artworkDateMatDim.type('artworkDetails').all())
%}

But I'm still getting only "one half" of the Matrix fields that I'm after.

I think your problem might be that you're overwriting the metaDescribe variable on each iteration of your for loop at the end of your first example. Given that you know you'll only be dealing with two blocks, you could try replacing the loop with something like this:
{% set metaDescribe = artNameMat[0].artistName ~ ' ' ~ '(' ~ artNameMat[0].birthDeathLocationDate ~ ')' ~ ' ' ~ artNameMat[1].materials ~ ' ' ~  artNameMat[1].dimensions  %}

[Aside: it may also be worth revisiting your content model, as it sounds a little convoluted! Investigate the possibilities of moving some pieces of content out into dedicated sections or category groups and using relationships to tie everything together.]


3.2 upgrade, drafts table error When I try to upgrade to 3.2 on my site I get an error saying the drafts table already exists.  Does anyone know of any plugins that use such a table?  I'm trying to sort out what's going on.

Sounds like you didn't completely roll the database back to 3.1 before re-trying the update. That table probably got created the first time you tried to update to 3.2.

Make sure the database is wiped 100% clean before rolling back to your 3.1 database. Then try updating again.


FormBuilder - PHP notice Trying to get property of non-object I'm trying to do a form, I'm using FormBuilder plugin.
I have the form and the fields, but when I try to acess ../admin/entries to manage the content of the page, I have this error, why is that? What did I miss?
I The code in that page:

{% block content %}

{{ entry.title }}

<form method="post" accept-charset="utf-8" name="{{ form.handle }}" class="formbuilder-form" id="{{ form.handle }}" data-parsley-errors-container=".formbuilder-notification"{% if form.hasFileUploads %} enctype="multipart/form-data" {% endif %}>
<input type="hidden" name="action" value="formBuilder/entries/saveFormEntry">
<input type="hidden" name="formredirect" data-redirect="{{form.successPageRedirect}}" value="{{form.redirectUrl}}">
<input type="hidden" name="formHandle" value="{{form.handle}}">

{% for tab in tabs %}
  {% set fields = tab.getFields() %}

  <fieldset class="{{loop.index}}">
    <legend>{{ tab.name }}</legend>
    {% for field in fields %}
      {% set input = craft.formBuilder.getInputHtml(field) %}
      {{ input | raw }}
    {% endfor %}
  </fieldset>
{% endfor %}

{# Error/Success Messages #}
{% if craft.session.hasFlash('error') or craft.session.hasFlash('success') %}
  {% if craft.session.hasFlash('error') %}

{{ craft.session.getFlash('error') | raw }}

{% endif %}
  {% if craft.session.hasFlash('success') %}

{{ craft.session.getFlash('success') | raw }}

{% endif %}
{% else %}

{% endif %}

<button type="submit">Submit Message</button>

</form>

{% endblock %}

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

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

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


Craft version number in database? My provider upgraded to PHP7 and deleted all files outside of the public folder, where I had the system files (...). Is it possible to find out from the database which version (of Craft 2) I need to restore the website?

I think I've already found it:

`craft_info` (`id`, `**version**`, `schemaVersion`, `edition`, `siteName`, `siteUrl`, `timezone`, `on`, `maintenance`, `dateCreated`, `dateUpdated`, `uid)

I can download the correct version from this great service: https://craftcms.com/support/download-previous-versions


How do you modify the entry data before the template is rendered? I am using a pattern library which expects a different data structure to what is in entry. Is there a way to parse the entry through a transformer class before the template is rendered?

Currently I have created a Twig function to run: {% set job = single(entry) %} which returns the mapped data for each different entry type.

I would like to hook into Craft to do this before the template is rendered and remove any mapping logic from the templates. Is this possible/practical?

Definitely possible; you'd need to write a plugin or module in PHP to do it though. Probably it could listen to for the View::EVENT_BEGIN_PAGE event, and get the injected element via $element = Craft::$app->urlManager->getMatchedElement()

Something sorta like this:

use craft\web\View;

// ...

    $request = Craft::$app->getRequest();
    if ($request->getIsSiteRequest()) {
        // Handler: View::EVENT_BEGIN_PAGE
        Event::on(
            View::class,
            View::EVENT_BEGIN_PAGE,
            function () {
                Craft::debug(
                    'View::EVENT_BEGIN_PAGE',
                    __METHOD__
                );
                $element = Craft::$app->urlManager->getMatchedElement();
                if ($element !== null && ...) {
                    // ...do something
                }
            }
        );
    }

To make things clean, rather than modifying the element itself, I'd probably inject a new Twig variable, something like entryTransformed or something that your templating code could access.


Redactor denied tags replacement? Has anyone found a replacement for:

deniedTags: ['p'],
paragraphize: false

I can't find a way to strip the pesky <p> tag anymore, on Redactor II.

I guess with Redactor II you "manually" have to make sure you cannot create those tags with buttons/shortcuts or by pasting in rich text.

Button configuration works with the formatting and formattingAdd settings.
Paste config settings were added with Redactor II 1.2 (Craft 2.bla), the ones you're probably interested in are pasteBlockTags and pasteInlineTags.

Redactor II deprecated the paragraphize setting and automatically wraps each paragraph in <p> tags. If you also want to prevent <p> tags, removing them on a template level using a Twig filter like striptags is probably your best bet at the moment (→ see Redactor II Craft 2.5 Prevent Paragraphs).


If no blog entries, show something else I'm having a bit of trouble showing a message if there's no entries in my blog. I tried the length filter but my empty message wont show:

{% for entry in craft.entries.section('volunteerPosition').find() %}
  {% if entry.volunteerPosition|length %}

      {{entry.volunteerShortDescription}}

  {% else %}

      Sorry, Nothing to show.

  {% endif %}
{% endfor %}

This should do it:

{# Get all of the entries in the 'volunteerPosition' section #}
{% set entries = craft.entries.section('volunteerPosition').find() %}

{# Do we have any %}
{% if entries|length %}

    {# Loop through them #}
    <ul>
        {% for entry in entries %}
            <li>{{ entry.volunteerShortDescription }}
        {% endfor %}
    </ul>

{% else %}
    {# Nothing to see here #}
    Sorry, nothing to show.
{% endif %}


Strange cached url prefix with caching Craft Pro 2.4.2702

Experiencing an intermittent issue with a Craft site that randomly crops up. It always seems to occur randomly with the caching and the "www" prefix and URLs being cached.

In a Redactor WYSIWYG field, this is the markup.

Privacy Policy

Randomly at times the page, the page URL links will be cached like so. Notice the eww.mysite.org. I've seen other instances where it's been ww.mysite.org/page-url, eee.mysite.org/page-url, htp.mysite.org, wee.mysite.org for all URLs that are being cached in the craft_templatecaches table. The urls are generated by entry.getUrl(), but also are manually typed in using a WYSIWYG field.

With my previous example, this is how it's being cached in the database
Privacy Policy

Majority of the caching on the site is done like so.

{%- cache globally unless craft.config.devMode -%}
...
{%- endcache -%}

At first I thought this might have been the wildcard in the DNS (*.mysite.org) and the page was still resolving with any prefix value and the URLs were being cached like so. I since then have removed the wildcard from the DNS, the page no longer resolves with an incorrect prefix, and this issue seems to pop up randomly.

In my general.php config.

define('URI_SCHEME',  ( isset($_SERVER['HTTPS'] ) ) ? "https://" : "http://" );

define('SITE_URL',    URI_SCHEME . 'www.' . $_SERVER['SERVER_NAME'] . '/');

Htaccess file.

# ----------------------------------------------------------------------
# Rewrite Craft URLs to remove index.php
# ----------------------------------------------------------------------

    RewriteEngine On

    # ----------------------------------------------------------------------
    # Force "www." to beginning of URLs
    # http://stackoverflow.com/questions/4916222/htaccess-how-to-force-www-in-a-generic-way
    # ----------------------------------------------------------------------

        RewriteCond %{HTTP_HOST} !^www\. [NC]
        RewriteCond %{HTTP_HOST} ^mysite.org [NC]
        RewriteCond %{HTTPS}s ^on(s)|
        RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

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

A user on their local machine/intranet has a wildcard value setup to resolve to the servers IP address. Even though the DNS is configured to disregard any wildcard value, it seems as though a wildcard value is setup the point to the servers IP on a local/intranet machine.

What was happening was users mistyping the URL. With a typing of the URL "www", the page was still resolving and becoming cached in Craft.

From my local machine, I edited my host file to test this theory and it turned out to be the case.

Found that my rewrite conditions in the htaccess were messed. I've updated my htaccess rules as well (Arcustech server). Forces "WWW" over SSL.

RewriteEngine On

    # If SSL request WITHOUT WWW
    RewriteCond %{ENV:SECURE_REDIRECT} on
    RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
    RewriteCond %{HTTP_HOST} !^(local\..+|staging\..+|.+dev)$ [NC]
    RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

    # If NOT SSL request WITHOUT WWW
    RewriteCond %{ENV:SECURE_REDIRECT} !=on
    RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
    RewriteCond %{HTTP_HOST} !^(local\..+|staging\..+|.+dev)$ [NC]
    RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

    # If NOT SSL request WITH WWW
    RewriteCond %{ENV:SECURE_REDIRECT} !=on
    RewriteCond %{HTTP_HOST} ^www\..+$ [NC]
    RewriteCond %{HTTP_HOST} !^(local\..+|staging\..+|.+dev)$ [NC]
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

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


Duplicate meta descriptions when category has multiple pages Does anyone know how to solve the problem of duplicate meta descriptions appearing when a category has multiple pages?

For example:

Category: Telephones
Pages: 5 pages

All 5 pages end up with the same meta description, titles and keywords. Only the content is changeable?

I would add custom fields to your category group, for META Descriptions. This would allow you to display meta data when on a 'category home page'.

Then on a single entry page, the entry-type custom fields for meta data would be used.

See this example/answer: How do I define an entry's META description?


loop through an entry's "related entries", grouped by category Hope somebody can help us with this:

Objective: loop through a given Entry's "Related Entries" entry field and output the results - but group the results by the category to which they belong - not just a straight splurge of related entries.

Where we are:

{% for category in categories %}

{{ category.title }}
{# spit out the Category #}

{% for relatedEntry in entry.relatedEntries %}
    {{ relatedEntry.title }}{# this spits out all entries, but ignores whether the entry is related to the current category #}

    {# So, try and check if it's related to the current category... #}
    {% if relatedEntry.relatedTo(category) %}{# Trying to use this throws "Craft\EntryModel and its behaviors do not have a method or closure named "relatedTo"." #}

{{ relatedEntry.title }}

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

Try this:

{% for category in categories %}
    <h2>{{ category.title }}</h2>{# spit out the Category #}

    {% set entries = craft.entries.section('news').relatedTo(category) %}
    {% for relatedEntry in entries %}
        {{ relatedEntry.title }}
    {% endfor %}
{% endfor %}

See the set entries = ... line.

I am retrieving the entries that are related to each category as it loops thru each category.


Change system settings email address Is there a way to change the email address stored in the craft_systemsettings table?

I guess this was originally setup when installing Craft but now I need to change it. I've changed the email address in the user account but this is not modifying the craft_systemsettings table. I could go into the phpMyAdmin and modify the MySQL but this feels like quite a clunky process.

Is there a better way?

I think you are referring to the System Email Address under "Settings" -> "E-mail" -> "System Email Address".


Sprout Form redirect after submit not working correctly All my forms on sprout form won't use the redirect they get assigned via the Form builder. Whenever a form is succesfully submited it redirects to my homepage instead of my thank-you page.

<form class="form__regular" method="post" accept-charset="UTF-8" id="contact-form">
    {{ getCsrfInput() }}

    <input type="hidden" name="action" value="sprout-forms/entries/save-entry">
    <input type="hidden" name="handle" value="{{ form.handle }}">
    <input type="hidden" name="redirect" value="{{ form.redirectUri }}">
</form>

Even if I write the redirect URL manually it keeps redirecting me to the homepage.

The only way I can get the redirect to work is when I let sprout forms render the fields.

In Craft 3, Form redirect values must use the hash filter:

<input type="hidden" name="redirect" value="{{ form.redirectUri|hash }}">

It's mentioned in passing in the docs here.

Without that hash filter, you'll get redirected to the home page as you are experiencing.


List entries for a single tag from blog section I want to get a list of entries in a template that have one specific tag 'weddings' and exclude entries that do not have this tag.

{% set tag = craft.tags.search('weddings').first() %}

{% if tag %}
  {% set entries = craft.entries.relatedTo(tag) %}
  {% for entry in craft.entries.section('blog').limit(5) %}
    {# get stuff #}
  {% endfor %}
{% endif %}

But this gets me all blog entries - even those without the Tag weddings. What am I missing?

You were very close! You are looping through craft.entries.section('blog') which doesn't use your tag query. You simply need to loop through the results of your query which you've set in the entries variable.

You may want to grab your weddings tag using the tag's id or slug as .search will find any tag with the string 'weddings' in it.

It might also be a good idea to use the conditional to check entries is returning something first, before outputting it.

{% set tag = craft.tags.slug('weddings').first() %}
{% set entries = craft.entries.relatedTo(tag) %}

{% if entries|length %}
  {% for entry in entries.limit(5) %}
    {# get stuff #}
  {% endfor %}
{% endif %}


Pushing additional key values without overwriting existing key values in an array For an existing key in an associative array, I'm trying to push a new value to it without overwriting the existing values in the key. I've tried this:

{% set myArray = {
    myKey: [
        'value1',
    ]
} %}
{% set myArray = myArray|merge({key: 'value2'}) %}

But this returns [ 'myKey' : 'value2']. I'm trying to get it to return [ 'myKey' : [ 0 => 'value1', 1 => 'value2'].

This should do it for you:

{% set myArray = {
    myKey: [
        'value1',
    ]
} %}

{% set myArray = myArray|merge({myKey: myArray.myKey | merge(['value2']) }) %}


Developing in Teams - What is the best Craft setup? We are currently working on a Craft project with 3 developers.

Our setup:
3 Local machines running Laravel Homestead and a local DB + Craft.
1 remote server holding Craft + db.

Our workflow:

We are using Github for version control of our local files.
For the DB we are currently using a dumb workaround we are very unhappy with :) . We are saving the DB in the craft-cp and git pushing the export to whatever branch we are working in. Then the next person has to import it locally whenever he makes changes to it.

We just thought using the same remote db on our server would be a better idea. Any better ideas? Is there something as good as Github but for DBs?
Or is there a better way to collaborate on a craft project anyway?

The articles might be useful to you:

Database & Asset Syncing Between Environments in Craft CMS

Multi-Environment Config for Craft CMS


Output matrix field data I have a matrix field with a block called "employment", under this block are fields, one of those fields is a drop down.

I'd like to be able to output the drop down field as a select list so users can choose from it.

Note: that I'm NOT trying to output what a user has selected, I just want to output the options from which a user can select.

Thanks!

UPDATE

That's not really what I'm after. Let me be more clear.

The matrix field I'm speaking of is attached to the user model but I'm not trying to output the user's data saved for the matrix. What I'm trying to do is simply output a field of a given matrix.

I am able to load the matrix doing this:

{% set matrix = craft.fields.getFieldByHandle('employmentMatrix') %}

But I'm not sure how to access the matrix's blocks then fields. I tried this:

{% set matrix = craft.fields.getFieldByHandle('employmentMatrix') %}

{% set blocks = craft.matrix.getBlockTypesByFieldId(matrix.id) %}

But I get an error saying "matrix" is not a method.

Assuming you have an entry to work with, something like this should work:
{% for block in entry.myMatrixFieldHandle if block.type == "employment" %}
    <select>
        {% for option in block.myDropDownFieldHandle.options %}
            <option value="{{ option.value }}">{{ option.label }}</option>
        {% endfor %}
    </select>
{% endfor %}

Otherwise you may need to get the field through the fieldLayout or by it's handle.
Update
craft.matrix is not exposed to twig like it is in php. To get the dropdown field options through the matrix field directly you'll have to go the long way around (matrix > blocktypes > blocktype > fields > field > options)
{% set matrixField = craft.fields.getFieldByHandle('employmentMatrix') %}
{% set blockTypes = matrixField.getFieldType.getSettings.getBlockTypes %}
{% for blockType in blockTypes if blockType.handle == "myBlockTypeHandle" %}
    {% for field in blockType.getFields() %}
        {% if field.handle == "myDropDownFieldHandle" %}
            <select>
                {% for option in field.settings.options %}
                    <option value="{{ option.value }}">{{ option.label }}</option>
                {% endfor %}
            </select>
        {% endif %}
    {% endfor %}
{% endfor %}

UPDATE: This is for craft 2. For craft 3 see Nathan S answer below.


Limitation of adding a Category from the CP field modal within an entry Is there a way to either add a parent selector to the category field modal, or remove/hide the "+ New Category" button when editing an entry?

We are using a category group to contain Locations, which are nested as State > County > City. I recently noticed that several new Cities have been added to the site, but they are all at the root level instead of being nested under the correct State and County parent categories.

This is because when an author creates a new City via the Location field modal while adding or editing an entry, there is no visible way to specify a parent like there is when adding it from the main Categories CP area.

I can see this getting out-of-hand quickly without some way to keep these categories nested properly, so any advice would be appreciated.  Thanks!

The easiest solution is to simply hide that DOM element using Control Panel CSS.


RedactorClips and RedactorStyles plugins not working I have both Redactor Clips and Redactor Styles plugins installed, but neither seem to affect my rich text editor (i.e., i don't see any extra buttons). Are there known issues?

Did you add the buttons to your toolbar by editing or adding a config file:
/craft/config/redactor/my_custom_toolbar.json?

You can configure multiple redactor setting files and apply them individually to your rich text fields from the field settings.


Problem with switch statement in language picker - [Solved] I made a language picker, it works in one language but not in other. I want to get the current page of other locale.

{% set locale = craft.i18n.getCurrentLocale() %}

 {% switch locale %}

  {% case 'en_us' %}
   Deutsch
  {% case 'de' %}
   English

 {% endswitch %}

Works in first case but not the second. What am i doing wrong?

Update: I forget to update the locale template in other language. Problem is solved, my mistake.

I forget to update locale template code with the same switch statement. Now problem solved.


Filter results after searching Is there a kind of “search in results after you retreived all entries” thing? Thing is: I have this query:
craft.entries.section('players').limit(null)

I want to show all entries where playerPosition = goalie. And on the same page, I want to show all players where playerNationality = Nederlands. And on the same page I want to show the longest player (sorted by playerHeight).

I can off course run a query 3 times:

goalies = craft.entries.section('players').playerPosition('goalie').limit(null)
nationalplayers = craft.entries.section('players').playerNationality('Nederlands').limit(null)
longest = craft.entries.section('players').order('playerLength desc').first();

That would work, but I'm running a query 3 times on the same section. There must be a better way, right? – Some have told me about the SuperSort plugin (which was indeed the right solution for my previous question), but that only sorts results. It's not a real filter.

You've got your two obvious choices nailed down.  You're either offloading the filtering to MySQL (running 3 separate queries so that MySQL filters the data) or you're grabbing all of the data and filtering it on the Twig/PHP side.

Which one is more performant likely depends on 1) how much data you're talking about and 2) your environment (resources allocated to MySQL vs. PHP).

For your particular case, I'd enable devMode and analyze the performance metrics between the two methods while taking into account how fast the data might increase in the future and make an educated guess based on that information.


Going from a static site generator (Jekyll or Hugo) to Craft CMS; Export/migrations options? I currently have a website that's been built using a static site generator (SSG; in this case, Hugo). The site has about 10 sections, each with 40-50 markdown files. As is the case with most content built out using an SSG, the content files are all well structured and include embedded metadata (via YAML front matter) at the top of each content .md file.

The front matter is very well structured and includes the following fields across all article files:

title:
subtitle:
description:
tags:
categories:

There is also a staff/person content type with the usual fields:

name_first:
name_last:
job_title:
reports_to:
Etc...

With Hugo (or just some clever BASH scripting), I can easily template these into a CSV (or multiple CSVs), JSON, etc. I know there are obvious differences between flat files/serialized data and an RDBMS, but I'm wondering if there is a clever way for me to make all of this content easily importable for Craft CMS 3, which our company is hoping to use for a major replatforming in about 3-4 months.

The entire site actually has close to 650 pages, but I figure I can start structuring them in markdown with YAML first to avoid a prolonged copy-and-paste nightmare. (Our current "CMS" is not a CMS by any means and doesn't contains any metadata.) I can parse the content out as very clean HTML, plain text, etc.

Any thoughts, first steps, suggestions, etc would be extremely appreciated. Thanks!

There is a good plugin called FeedMe that can help with imports. We used it migrating a pretty large EE site without issue. If you can spit out a XML, RSS, ATOM or JSON feed, it should be able to import it.

FeedMe Plugin

I am not sure if it is Craft 3 ready yet, though.


Search by ID in the CP Unless I'm missing something, it seems like it is impossible to search by ID in the CP (and therefore via ElementCriteriaModel's search).

I know you can make it sortable using modifyEntrySortableAttributes, but it still doesn't make it searchable.

I've also tried id::"123", which doesn't work.

Any way to do this?

If you analyze POST request you will see this:

To get items by id you need to create custom request and add criteria[id]=(int id here) e.x. use this

It is most likely related to the way how ElementCriteriaModel works (99% sure) :

craft.entries({
    id: 123, // search by ID*
    search: 'search query'
})

search by ID*

craft.entries returns ElementCriteriaModel - Source

You won't be able to use default CP search form to get entries by ID


Which section type for Craft Commerce customer account pages I looking for suggestions for customer account pages.Something like;

account
 account/addresses
 account/my-orders
    account/orders/order-5566
    account/orders/order-5567

Which section type should i use Structure, Channels or Singles? Or just use folder/file templating structure?

I know Stackexchange is not a place for open ended questions but couldn't find any good example on this.

If you need user profile data, the obvious place to store that is in Craft Users.  Add the fields you need etc.

Commerce has a field you can add to a User to show that user's addresses and orders on the back end.

For the front end, you then just make user profile page templates as you need them.

I see no good reason to use Structures,Channels or Singles here really, although I guess it depends on what other content you might want to have on those pages.  For the most part you're probably either just looping over the addresses and orders, or showing a single entry page for one of those.

Of course Craft is so flexible, you could use a structure for some of it, if you have fuller content needs, and then dynamic templates for those more transactional pages...there's an almost limiteless variety of ways you could do it, but user fields plus some templates for those sorts of pages would be the 'most standard' approach.....certainly it's what we're using.


Updating Craft 3 from RC3 to RC4 through Composer I have a problem when updating with Composer.

My installation command line was this one:

php composer.phar create-project -s RC craftcms/craft $HOME/craft

As such, I tried to update, as per Ryan from Mijingo instructions:

php composer.phar update craftcms/craft

But I ended up with the following error:

Composer could not find a composer.json file in /home/me
To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section

I checked, composer.json and composer.lock are in the craft directory, as expected.

After looking through Composer man page and web docs, I am still clueless, as I haven't found what -s RC are used for in the installation command. I believe understanding these (this?) switches is probably the key, but I rather ask here than making a mistake and blowing the otherwise perfectly working install. ^^

As for the CP, it doesn't work either, but that is not a surprise given the command line didn't and that I am using the php composer.phar method rather than the sole composer one.

So, not all hosts allow just using composer and impose to use php composer.phar.

Knowing that, I can now answer my two questions:

When installing Craft using php composer.phar create-project -s RC craftcms/craft $HOME/craft, the -s switch is just telling which branch of the source project to use. Here, RC stands for Release Candidate. Before that, we had to use -s BETA in order to install the betas. Something I didn't knew since I waited for the RC to jump in Craft 3 and start over from Craft 2.
When you want to update using php composer.Phar, you need to go inside your project folder (where you installed Craft; craft for me which means once logged I had to cd craft) and then type php ../composer.phar update, where ../composer.phar tells to go looking for Composer from the parent folder.

I am ashamed not having thought of that; I really need to stop overthinking things.


Visiting any locale gives the same locale output The site has 5 locales targeting 'en_gb', 'fr_fr', 'de_de', 'it_it', 'es_es'.
When I'm at site.com it gets current locale correctly en_gb. When I visit site.com/fr/ locale, It loads blank page with current locale en_gb. The same scenario repeats for all locales, except the top level local en_gb.

I went through my settings multiple times, but I still wasn't able to find a problem.

My general.php settings:

return array(

// Local environment
'site.craft.dev' => array(
    'devMode' => true,
    'environmentVariables' => array(
        'sitePath' => '/OS/Applications/MAMP/sites/site.craft.dev/public/',
        'siteUrl' => 'http://site.craft.dev/'
        ),
    'siteUrl' =>  array(
        'en_gb' => 'http://site.craft.dev/',
        'fr_fr' => 'http://site.craft.dev/fr/',
        'de_de' => 'http://site.craft.dev/de/',
        'it_it' => 'http://site.craft.dev/it/',
        'es_es' => 'http://site.craft.dev/es/',
        ),
    )
);

Public folders are structured  and set according to documentation, named after locale's handles like that: fr_fr, de_de etc.

and with $craftPath variable set to necessary handle like fr_fr, de_de etc.

When I visit site.craft.dev/fr/ and ask for current locale by {{ craft.i18n.getCurrentLocale() }}, it gives me default locale en_gb.

The craft path should be 1 level deeper like that '../../craft' instead of '../craft'. This is what was causing it, but I had to reconfigure the locales from fr_fr to fr. It didn't work in original way.


Default Users Password Regex Assume a front end registration form. I would like to validate user passwords before posting to the server. I have not been able to find the default password requirements as of yet for craft 3. Could someone fill in the blank?

From what I have found:

At least one capital letter
At least one lowercase letter
No more than 160 characters

There are a couple of existing plugins that look like they might do what you're looking for:

https://plugins.craftcms.com/password-policy

https://plugins.craftcms.com/enforce-password

And of course, you could always write a plugin that meets your exact requirements as well.


$request->send fails on one server but not the other Not sure whether this is a Craft thing or a Yii thing, but I have this exact same code running on two servers that I've freshly updated Apache, PHP, etc. On the one server it runs fine but on the other the page never loads and I have to do a server reboot to clear it.

Can anyone think of any reason this might happen?

$url = 'https://domain.com/jsonfeed'
try {
    $client = new \Guzzle\Http\Client();
    $request = $client->get($url);

    // BREAK NOW AND ALL IS FINE

    $response = $request->send();

    // BREAK NOW AND PAGE NEVER LOADS SO IT MUST BE
    // $request->send(); THAT IS FAILING

    if (!$response->isSuccessful()) {
        return;
    }

    $items = $response->json();

    reset($items);
    $key = key($items);
    return $items[$key][$id];

} catch(\Exception $e) {
    return;
}

The problem was the service that was supposed to return the JSON feed was not returning anything. Meaning our server was simply waiting for a response that never arrived and eventually timing out a minute later.

I only discovered this by writing my own script to test for a response from two different servers, discovering the IP address of the server experiencing the problem was being blocked from accessing the JSON feed.

Please, if you're supplying data and decide to block someone's IP, at least tell them you're doing so. An error response would have saved me a lot of work.


Add Tags to a Newly Created Entry With PHP in Craft 3 I am able to successfully create new entries with PHP when I am using basic field values that are Rich Text or Plain Text fields, but am unsure how to add Tags to an entry.

So my entry already has a field called 'tags' on it, and I thought that maybe it wanted an array of strings like so:

$entry->setFieldValues([
   'tags' => array('someCoolTag', 'tagasaurus rex')
]);

I admit I do not really understand how tags work behind the scenes, and would like to correct that. Any help is great.

Tags are normal Elements like Entries, Categories, Users and so on.. In order to relate a Tag to another element, you need to insert the array of those elements like you are used to with every other field

$existingTag = Tag::find()->title('whatever')->one();

$tag = new Tag();
$tag->groupId = 1; //<-- insert your group id here
$tag->title = "something";
Craft::$app->getElements()->saveElement($tag);

$entry->setFieldValues([
   'tags' => [$tag->id, $existingTag->id]
]);


Plugin sending emails to all users in an entries Users field I have a channel set up with front end submitted entries. I want a way for users to be able to subscribe themselves to receive an update whenever the entry (or it's related entries) are updated. I was thinking one way to so this so that it can be managed on the front end would be to add a Users field to the entry and let logged in users add themselves to it.

I have a simple notification service that I am using in a custom plugin that is sending emails to entry authors, but I'm not sure how, or what would be the best way to send emails to multiple users as per the above requirement.

(p.s I'm new and limited in my plugin knowledge!)

Any thoughts or suggestions.

Thanks!

If you have questions or other issues feel free to ask.
Please don't be confused, my Plugins handle/name is "Test" because I only use it for these purposes.. So whenever you see the name "Test" you know you have to rename it

This is your plugins init function

/**
 * Called after the plugin class is instantiated; do any one-time initialization here such as hooks and events:
 * @return mixed
 */
public function init()
{
    parent::init();
    craft()->on('entries.onBeforeSaveEntry', function(Event $event)
    {
        // trigger only when entries are changed not when created
        if(!$event->params['isNewEntry']){
            /** @var EntryModel $entry */
            $entry = $event->params['entry'];
            // create your logic to check if it is the correct entry...
            // you should check for your section here otherwise you'll send a mail for all updates^^
            // I just used the handle pages in my test system
            if($entry->getSection()->handle === "pages"){
                // next: fetch all user related to the entry...
                // since I don't know your entire fields, you have to implement the logic
                // to fetch users from entries that are related to the entry yourself
                // if you need help just ask
                $criteria = craft()->elements->getCriteria(ElementType::User);
                $criteria->relatedTo($entry);

                /** @var UserModel $user */
                foreach( $criteria as $user){
                    // create a new entry in the database
                    $email = new Test_EmailRecord();
                    $email->entryId = $entry->id;
                    $email->email = $user->email;
                    $email->save();
                }
            }
        }

    });
}

And you have to create the following record

namespace Craft;

class Test_EmailRecord extends BaseRecord
{
    public function getTableName()
    {
        return 'cron_mails';
    }

    protected function defineAttributes()
    {
        return array(
            // you could store the user Id here too, but this way
            // you can send the mail to non users too
            'email' => AttributeType::String,
            'entryId' => array(AttributeType::Number),
        );
    }

    // you could - if you want - create relations here..
    // https://craftcms.com/docs/plugins/records#defining-relations
    // but since it's only an example and not needed I skipped that part
}

And you need this in your controller

 /**
 * Cronjob to send emails... you can activate it every X hours
 * or once per day or whatever you want
 * when this function is trigger a specific number of mails will be send
 * their entries in the database will be deleted until there are no rows in the
 * table
 */
public function actionSendMails()
{
    // fetch mails with limit.. insert your limit here.. I would suggest to fetch 20-50
    // entries per trigger depending on how often it should run
    $emails = Test_EmailRecord::model()->findAllBySql('select * from craft_cron_mails LIMIT 1');

    if (is_array($emails) && count($emails)) {
        foreach ($emails as $email) {
            /** @var UserModel $user */
            $user = craft()->users->getUserByEmail($email->email);

            // do your logic if no user is found..
            // of course you could store the user Id rather than the email in the database table
            // but this way you can send the mail to non users too if you like
            if (!$user) {
                // you can just remove that part
                // I just wanted to show you could create an array with defaults here
                // if the user is not registered
                $user = array(/* fill some placeholders for your twig template */);
            }

            // prepare templates, you can address each user personally with a hello Mr {{ user.name }}
            // the entry {{ entry.title }} was edited and such...
            $message = craft()->templates->render('path/to/template.twig', array(
                'user' => $user,
                'entry' => craft()->elements->getElementById($email->entryId)
            ));
            if ($this->sendMail($message, "The post was edited", $user->email)) {
                //remove the column if the mail was send
                $email->delete();
            }

        }
    }
}

/**
 * This function sends the mail, it usually belongs to a service
 * but to make it easier I'll just leave it here
 *
 * @param $message
 * @param $subject
 * @param null $mail
 * @return bool
 */
public function sendMail($message, $subject, $mail = null)
{
    $errors = false;
    $adminEmail = craft()->systemSettings->getSetting('email', 'emailAddress');

    $email = new EmailModel();

    $email->fromEmail = $adminEmail;
    $email->replyTo = $adminEmail;
    $email->sender = $adminEmail;
    $email->fromName = craft()->getSiteName();
    $email->toEmail = $mail;
    $email->subject = $subject;
    $email->body = $message;

    if (!craft()->email->sendEmail($email)) {
        $errors = true;
    }

    return $errors;
}


I cannot get the email address to properly update from my user account management form I figure I must need to pass the current user's password along with the updated email address upon form submit. However, I cannot get the email address change to take. Any help is greatly appreciated. Here's my code snippet:

<form action="" method="post" accept-charset="UTF-8" enctype="multipart/form-data" class="account-edit">

    {{ getCsrfInput() }}

    <input type="hidden" name="action" value="users/saveUser">
    <input type="hidden" name="password" value="{{ currentUser.password }}">
    <input type="hidden" name="redirect" value="account">
    <input type="hidden" name="userId" value="{{ currentUser.id }}">
    <input type="hidden" name="deleteUserPhoto" id="deleteUserPhotoInput" value="">

    {% if currentUser.firstName %}

            First Name

            <input name="firstName" value="{{ currentUser.firstName }}" class="form-control">

    {% endif %}

    {% if currentUser.lastName %}

            Last Name

            <input name="lastName" value="{{ currentUser.lastName }}" class="form-control">

    {% endif %}

    {% if currentUser.email %}

            Email

            <input name="email" value="{{ currentUser.email }}" class="form-control">

    {% endif %}

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

                Delete

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

    {% else %}

    {# If no photo exists, give the option to upload a new one #}
        Upload Photo

            <input type="file" name="userPhoto" value="Upload">

    {% endif %}

    <input type="submit" value="Update Account" class="btn profile-save">
</form>

As of Craft 2.3, the rules for changing an existing password are:

If you're editing your existing account OR you're an administrator OR you have the 'changeUserEmails' permission set on your user account, then you need to supply your existing user account's password as a hidden input (not the current password for the account you're trying to change).

<input type="text" id="currentPassword" name="password" />


Craft update process affecting Element API cache I have a site A using the Element API plugin to feed content to site B via JSON and handlebars templates. The process is both sites are up to date with content 'x' and it works fine.

When I run the CP updates on site A and it finishes the data on site B never shows until the site A cache is cleared.

Is this expected behavior?

Got to the bottom of it. It was a CORS thing - permission with the domain htaccess and elementAPI. A shift from non-www, to www redirection seemed to be the cause so now solved


Is it possible to use something like dropzone.js for file uploads with sprout forms? I'm trying to come up with a nice UI experience for people to upload a CV and covering letter and I'm considering using something like http://www.dropzonejs.com/

I'm not sure how this would work with sprout forms because you have to put a action in the form to make it work (from what I can tell anyways)

Is there a solution for this or is there an alternative approach you know that would work?

You will have to upload the files and index them as assets, then return the asset id's to your form. You can then use these asset id's in your form so you can post them to the server, effectively creating the relations you want.

I've put up a little gist that does this for jQuery File Upload - you can use it as a reference for any other upload mechanisms: https://gist.github.com/boboldehampsink/2e645655d613574ec4b7


Current day display on day later in the CP settings, timezone is set to UTC +1 Europe/Zurich
when I try this code:

{% set currDay = now|date() %}
    {{ currDay|date('l d F Y') }}

it outputs "Mercredi, 16 janvier 2019", but we're still Tuesday 15th

Craft 3.0.37

Try

{% set currDay = now|date('M j, Y H:i:s') %}
{{ currDay }}

Applying the |date() filter to the now object when you set the variable currDay makes currDay a string. When you then try try to reapply |date() a second time, something funny must be happening..?


Paginate An Array Of Entries I have read through the docs and I am not sure if what I need to do is possible with array sets. I have filtered my entries using the following code"

{% set allDatabytes = craft.entries.section('databytes').limit(null) %}
{% set seriesCollection = [] %}

{% for databyte in allDatabytes %}

  {# get only the series databytes #}
  {% set series = databyte.series %}

  {# add the series databytes to the series collection #}
  {% for entry in series %}
    {% set seriesCollection = seriesCollection|merge([entry.title]) %}
  {% endfor %}

{% endfor %}

{# Output the filtered results #}

{% set filteredDatabytes = allDatabytes|without(seriesCollection) %}

  {% for entry in filteredDatabytes %}

{{ entry.title }}

  {% endfor %}

What I now need to do is add pagination to the filteredDatabytes set of content.

From The Example Below

This is my code which currently doesn't display any results. I guess you add the limit to the MyCriteria model (is that the correct term)?

{% set MyCriteria = craft.entries.section('databytes').series(':empty:').limit(10) %}

{% paginate MyCriteria as entries %}
    {% for entry in entries %}
        {{ entry.title }}
    {% endfor %}

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

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

As Victor rightfully points out, the {% paginate %} tags require an ElementCriteriaModel, so you can't do what you're doing in your first example because as soon as you call:

{% for databyte in allDatabytes %}

Craft hits the database and converts the ElementCriteriaModel into actual EntryModels.

We also don't have support, yet, for passing :empty: into things like AssetFields, TagFields, etc., which is why your second example won't work...  however that is on our list to add!

In this case, I think your best bet is going to be to do through the search service with something like this:

{# Search for 10 entries in the 'databytes' section where the 'series' assetField doesn't have anything selected. #}
{% set myCriteria = craft.entries.section('databytes').search('-series:*').limit(10) %}

{% paginate myCriteria as entries %}
    {% for entry in entries %}
        {{ entry.title }}
    {% endfor %}

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

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


How can I filter a for loop based on the value of a field? How can I filter a for loop based on the value of a field?

I tried filterByValue, but I do not know how to construct the statement.

This is NOT a category field.

I have this...

{% for line in craft.entries.section('docs').filterByVale('account: 05').all() %}
    {{line.lineItemTitle}} ({{line.lineItemTitle}}),
{% endfor %}

How do I do this?

Thanks

You don't filter a loop but you can attach certain criteria in your ElementQuery. craft.entries returns you an object of type EntryQuery (link to docs). You can search for specific entries based on different criterias by calling magic methods or function in your Query object.

For example: section('docs') will return only entries in the section docs. You can attach any field handle that is in your field layout as well.. In your case account('05').

{% for line in craft.entries.section('docs').account('05').all() %}
     {{line.lineItemTitle}} ({{line.lineItemTitle}}),
{% endfor %}

If you want to search for multiple values you can include them as array or comma separated string.

craft.entries
    .section(['section1', 'section2')
    .account('and, >=5, <=10')
    .anotherField('or, 3, 5')
    .someThingElse(['or' ,3 , 5])
    .all()

You can see all available syntax examples in the DB::parseParam() function


Error while accessing an associative array Here is the code:

{% if entry_name not in data and entry_total > 0 %}
    {% set data = data|merge({ (entry_name) : entry_total }) %}
{% else %}
    {% set data.entry_name = 10 %}
{% endif %}

Twig throws an error on the statement following else condition.  Unexpected token "punctuation" of value "." ("end of statement block" expected). How can I set the value of a particular element of this associative array?

There's not a pretty way to do it in Twig other than what you've done in the if part of your conditional.  Something like this should work:

{% if attribute(data, entry_name) is not defined and entry_total > 0 %}
    {% set data = data|merge({ (entry_name) : entry_total }) %}
{% else %}
    {% set data = data|merge({ (entry_name): 10 }) %}
{% endif %}