Having problems with dynamic Asset folders and {owner.slug} I have a Matrix field with four blocks currently, a header (text), explanation (rich text), slideshow (assets), and single image (assets). Both the slideshow and single image blocks have two fields, image and caption.

The image field is the same in both with the exception of the slideshow assets field allows multiple images to be uploaded while the single is obviously limited to one. Both have "Restrict uploads to a single folder?" and "Restrict allowed file types?" checked and the latter only allows images. Both also have the same Asset Location selected and {owner.slug} as the path. Recently I discovered that I can no longer upload images to {owner.slug}, instead Craft is trying to upload images to /craft/storage/runtime/assets/tempuploads/field_##.

I've checked file permissions for my assets directory and there shouldn't be a problem writing to it. I used to be able to create subfolders based on the entry slug and what's even more bizarre is that I can edit an existing single image or slideshow block image field and it will use/upload to the proper directory.

Any ideas why it would stop doing this?

According to Andris this is the expected behavior in this situation. The bug fix does make Craft work as intended but creates a slightly confusing workflow if you don't know what to expect. The good news is my expected behavior, which is to have assets available if {owner.slug} has been created in my assets folder already, is on the official list of features to implement. Well, assuming Andris doesn't go into a drunken stupor and forget to tell Brad or Brandon.


check if a route segment matches a section entry type So i added a route to a template that shows entries by entry types.
the way the template does it is by taking the last segment of the url, and using it as an entry slug for this filter:
craft.entries.type(craft.request.getSegment(3)).relatedTo(category)
So, how can i check if the string in the segment matches any of the entry types in that section, and if not - redirect to 404 page?

Take a look at the {% exit %} tag. You should be able to do something very similar, since your search will return no results if the entry type does not exist.

{% set entries = craft.entries.type(craft.request.getSegment(3)).relatedTo(category) %}

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


Craft model and populateModels() performance issue? I'm getting a big performance hit on front end requests (+15 seconds) when using a model to store / use data from one of my custom fieldtypes, cp requests for the same data appear unaffected.

The prepValue function:

public function prepValue($value)
{
    if( is_array($value) )
    {
        return FruitGrid_BlockModel::populateModels($value);
    }

    return $value;
}

And the model which is getting populated:

class FruitGrid_BlockModel extends BaseModel
{
    protected function defineAttributes()
    {
        return array(
            'row' => array(AttributeType::Number),
            'col' => array(AttributeType::Number),
            'sizex' => array(AttributeType::Number),
            'sizey' => array(AttributeType::Number),
            'entryid' => array(AttributeType::Number),
            'rules' => array(AttributeType::Mixed),
        );
    }

    public function getRuleClasses()
    {
        $string = '';
        if(is_array($this->rules))
        {
            foreach ($this->rules as $rule => $value)
            {
                switch ($rule)
                {
                    case 'fixedHeight':
                        $string .= ' height-'.$value;
                        break;
                    case 'desktopRuleOne':
                        $string .= ' desktop-'.$value;
                        break;
                    case 'tabletRuleOne':
                        $string .= ' tablet-'.$value;
                        break;
                    case 'mobileRuleOne':
                        $string .= ' mobile-'.$value;
                        break;
                }
            }
        }
        return trim($string);
    }

    public function getEntry()
    {
        $criteria = craft()->elements->getCriteria(ElementType::Entry);
        $criteria->id = $this->entryid;
        return $criteria->first();
    }
}

And pretty standard usage on the front end:

{% if entry.customFieldHandle|length %}

    {% for block in entry.customFieldHandle %}

{{ block.entry.title }}

{{ block.entry.text }}

        ...

    {% endfor %}

{% endif %}

Avoid calling block.entry multiple time per block since you only need to do that database query once. Alternatively you can use function memoization to cache the entry like this:

class FruitGrid_BlockModel extends BaseModel
{
    private $_entry;

    protected function defineAttributes()
    {
        return array(
            'row' => array(AttributeType::Number),
            'col' => array(AttributeType::Number),
            'sizex' => array(AttributeType::Number),
            'sizey' => array(AttributeType::Number),
            'entryid' => array(AttributeType::Number),
            'rules' => array(AttributeType::Mixed),
        );
    }

    public function getRuleClasses()
    {
        //...
    }

    public function getEntry()
    {
        if(!$this->_entry){
            $criteria = craft()->elements->getCriteria(ElementType::Entry);
            $criteria->id = $this->entryid;
            $this->_entry = $criteria->first();
        }

        return $this->_entry;

    }
}

This will only get the entry from the database once.

Also recommend renaming the rules attribute on the model to something like blockRules.

When you loop over the rules to create the ruleClasses string you may be looping over every rule created by the AttributeType declarations in your defineAttributes method.


What's the best way to skip CSRF for plugin controllers? I'm working on a plugin that'll create a private API for content authors to post entries to Craft from desktop-based scripts. These scripts post data to plugin controller actions (anonymous-allowed), where the plugin will first check for valid Craft user account details or a plugin-generated key.

Since I'm still enforcing authentication, what's the best way to disable CSRF checks just for these posts when CSRF is globally enabled?

Thoughts I've had:

Attempt to put the CSRF key and token in the $_POST data as early as possible. (Probably not even possible.)
Have the client (desktop) script grab the CSRF key+token just before posting. (Inconvenient, potentially failure-prone.)
Somehow prevent CSRF protection from being enabled for requests passed to this controller.

In Craft 3 this is a cinch:

class PluginController extends Controller
{
    // Disable CSRF validation for the entire controller
    public $enableCsrfValidation = false;

    ...

See the Yii2 docs for more control over inividual actions:
https://github.com/yiisoft/yii2/blob/master/docs/guide/security-best-practices.md#avoiding-csrf


Tweaking the Tweet Follow Button Require a little help with removing the pre-parsed text from Dukt's {{ twitterTweetButton() }}

This does not work....

The docs specify the following Twig functions:

text — Pre-populated text highlighted in the Tweet composer.
url — URL included with the Tweet.
hashtags — A comma-separated list of hashtags to be appended to
default Tweet text.
via — Attribute the source of a Tweet to a Twitter username.
related — A comma-separated list of accounts related to the content
of the shared URI.
size — Set to large to display a larger button.
lang — A supported Twitter language code. Loads text components in
the specified language. Note: does not affect the text of the cited
Tweet.
dnt — When set to true, the Tweet and its embedded page do not
influence Twitter targeting including suggested accounts.

This is what the function currently does

public function tweetButton($options = [])
{
    $dataAttributes = $this->getOptionsAsDataAttributes($options);

    $html = 'Tweet';

    return $html;
}

So it returns an a tag rather than a link. You should remove your outer tag but you can't place your custom text. You would have to use a string replace function

{{ twitterTweetButton()|replace({'>Tweet<':' >my custom text<' }) }}


Paginate Entries by Day This is giving me a surprisingly hard time. Has anyone tried to paginate entries by date, in this case, specifically by day; i.e.: First page loads today's posts, next page loads yesterday's, then the day before yesterday, etc.

I tried grouping items by date, as done in the archive page example, and then paginating the groups but it didn't work.

In this case I am using a combination of pagination + ajax to load more content when needed. However the needs of the project have changed, and paginating by number of items isn't the best approach. It'd be better to show content based on the date.

Anyone?

Instead of using pagination, you might try creating a custom route using tags for year/month/day. Those tags will be available as variables in the template that you can use to load that days entries and generate the nav for next/previous day, etc. Using ajax the uri won't be visible to the user anyway.

{% set postDate = year ~ '-' ~ month ~ '-' ~ day %}
{% set nextDate = postdate|date_modify('+1 day')) %}
{% set previousDate = postdate|date_modify('-1 day')) %}

{% set entries = craft.entries.postDate('and', '>= ' ~ postdate, '< ' ~ nextDate %}

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

    next
    previous

Not tested, but should be close. You'll need to modify the links to work with your ajax of course.


How to improve search performance on front-end? I am trying to improve the performance of our site search. I'm wondering if there is anything I can implement that may speed things up. Currently we have a search being sent to a results page. In the results page we have this call to the database.

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

query is returned from the q parameter in the url.

We are using a matrix field for all the main content blocks on the site. This field has 10 block types with a max of 7 fields in each. This is used on all entries across the site.

Looking at the profiler after running a query on a phrase that is very popular across the site it takes around 11s and queries the db 500+ times.

Any suggestions how we may reduce this time down? Or is this just a disadvantage of using matrix fields?

Have you looked into eager loading the Matrix field if you are on 2.6? This should vastly cut down on the number of queries needed.

The other thought could be to use the Preparse field plugin to push the matrix fields into simple text, and then direct the search query to only look at the title field and preparse fields.


Append a placeholder value to a text input field when form is submitted I have a Matrix field in my Craft control panel which contains content which creates a front end form.  If the form field has a placeholder text entered in my Matrix field, I would like that text to be submitted along with the user's text input.

If the user entered "100" in the front end form text input field, and my placeholder text is "bpm", the result I would like submitted is: "100 bpm".

Here's my text input field form code:

<input type="{{ row.inputType }}" name="{{ block.fieldName }}" class="gui-input" placeholder="{{ row.label }}">

Here's a screenshot of my Matrix field:

Here's a screenshot of my front end form:

I tried adding a hidden input field below the text input field but the problem I ran into is that all placeholder text is submitted regardless of whether the user actually filled out a field.

<input type="hidden" name="{{ block.fieldName }}" value="{{ row.label }}">

So let's say that the user filled out the "fetal heart rate" text field but did not fill out the "estimated gestational age". Using the hidden text field both "bpm" and "weeks" is submitted even if the user didn't fill out the "estimated gestational age" field.

Summary of my question: Is there a way to conditionally append a value along user text input? Example, if the user entered "100" for "fetal heart rate" in the front end form text input field, and my placeholder text is "bpm", the result I would like submitted is: "100 bpm". If he skipped filling out any other text input fields then no additional values are submitted (like "weeks").

You could either do this the JavaScript way (listen to onSubmit, grab DOM values, append if necessary, otherwise remove), or the PHP way (from a plugin).

I'll pseudocode the latter because I hate the former.

Generate a Craft plugin.
Have it listen for the onBeforeSaveEntry event.
Inside that event listener, you can check if the entry being saved belongs to the section you're interested in.
If so, check your Fetal Heart Rate field.
If its value is "bpm", set it to null or an empty string.
If it's anything other than "bpm", append " bpm" to its existing value.
Repeat 4-6 for the "Estimated Gestational Age" field.
Bob's your uncle.


Entries not saving CDbException We have a very strange issue here. On my computer I'm trying to save an entry. The process indicator keeps spinning for about five minutes before this exception comes up:

CDbException
CDbCommand faalde tijdens het uitvoeren van volgend SQL statement: SQLSTATE[HY000]: General error: 2006 MySQL server has gone away. The SQL statement executed was: SELECT `locale`
FROM `craft_locales`
ORDER BY `sortOrder`

It's triggered by this function:
$this->userSession->checkPermission('accessCpWhenSystemIsOff')

On first look this definitely looks like a server issue. But... when I test this on a windows computer, it never happens. It's just not saving from an osx computer (browsers tested on osx: chrome, safari, firefox). Also tested on different osx computers and different windows computers. All with the same result. Windows works, osx doesn't.
Does anyone have a clue what might be going on here? Thanks!

I had the same issue. Tried setting a bunch of mysql and php configs for timeouts, packet sizes, etc, and nothing would help. Finally found that turning off dev mode fixed it for me. Don't know why. Just thought I'd throw that out there in case someone else was having the same problem.


"Page not found. What’s worse, a hilarious 404 page can’t be found either." My file structure is:

User/me/www/Craft-2.3.2644/

I am using MAMP and MAMP Points to this folder as my 'server root'.

Everything inside and including my web root has 777 permissions.

Inside this folder are three items:

craft/
public/
readme.txt

I have a MySQL database:

Domain: localhost
User: root

I have pointed the db.php file to my server, with 'root' as the password.

My index.php file in my public folder points to ../craft which reroutes to /app/index.php (a file that does exist in that location).

The most positive result I can get when surfing to localhost/public/index.php is a message that reads as below...

  Page not found

  What’s worse, a hilarious 404 page can’t be found either.

With any other permissions I cannot access the folder because I'm not allowed (oops message).

And with any other mapping in the index file I receive a message:

  File not found

You need to point your webserver to the public directory as stated in the docs here. So in your case that would mean setting your vhost to point to: User/me/www/Craft-2.3.2644/public.

In that public folder you will find an index.php file, which tells php where Craft can be found, by default (which yours is) that will be ../craft.


PHP error after one click update I updated Craft to version 2.6.2798.

Since then I'm getting a PHP error:

Parse error: syntax error, unexpected '[' in /craft/app/fieldtypes/BaseElementFieldType.php on line 428

PHP version on the server is 5.53.

Any ideas to fix that issue?


Custom Clickable Image I've been using Craft CMS for a while, but haven't seen any way to get the following done:

Looking to create a page with a large image on it. The image would be overlayed with buttons that pop-out a text box or overlaid image. I'd like to place the pop-out boxes/graphics all over the image in specific places, but the creation interfaces I've seen only let me put one image after another in a list, or rectilinear fashion.
I'm hoping to create a map of a neighborhood where clicking on different buildings/elements pops out another window with more information regarding that area/element.

I hope this is understandable, if more clarity is needed please let me know.

Any insight would be greatly appreciated.

Thanks

Whilst this mainly seems like a front-end development question, and Dr_Codswallop has perfectly summed up some steps in the comments to tackle that, as an answer for the Craft CMS specific side of the question there is a plugin I have used in the past that is very helpful, but it is only for Craft 2.x:

Donkeytail

I have had a look through the plugin store and I can't find an alternative plugin for Craft 3.x, so it looks like you will need to follow Dr_Codswallops instructions and build up something manually if you are running this version of Craft.


How can I import users from WordPress to Craft CMS? I want to import users from WordPress to Craft CMS. How can I do that?

I don't know how to export users from WordPress, but importing them in Craft can be done with a plugin like Feed Me. There are other plugins out there too depending on the export file you can get out of WordPress.

If you don't know how to export users from WordPress, you'd need to ask that on the WordPress SE if that exists :)


How can I start a loop at a specific number? First off, I'd like to thank Jeremy for his help.

I have a set of add-on products that go along with my primary product. The options are a radio group.

I am using Multi-Add to tie everything together - and it's all working great. I'm able to add the primary and optional products to the cart.

Where I am hung up is, because I have a radio group - no matter which option I choose, I am always ending up with the last option being chosen.
Which makes perfect sense since that's the last radio in the group that gets picked up.

Here is what I have so far:

...
// items[1][qty] is a <select> input for the primary product
...

{% for foo in products %}
    <div class="radio">
        <label>
            <input type="radio" name="items[2][qty]" value="1">
               {{ foo.title }} &ndash; {% if foo.defaultVariant.price == 0 %} Included with registration {% else %} {{ foo.defaultVariant.price|currency(cart.currency) }}{% endif %}
        </label>
        <input type="hidden" name="items[2][purchasableId]" value="{{ foo.defaultVariant.purchasableId }}">
    </div>
{% endfor %}

As you can see whatever the last radio input is, will be the value that is picked up by Craft regardless of what the user has actually chosen.

So I thought since each radio is a product (with no variants), I could just use the loop index:

<input type="hidden" name="items[{{ loop.index }}][purchasableId]" value="{{ foo.defaultVariant.purchasableId }}">

Which works, but the loop will start at 1 each time. I am hung up on how I can start the loop at a specific number. Or, perhaps there is a better way?

If I were using checkboxes, I'd only have one option per product/input name.

I have also tried using a <select> element, but I get hung up on how I can offer a "No thanks" option.

<select name="items[2][purchasableId]" class="form-control required">
    <option value="">Select</option>
     {% for foo in products %}
         <option value="{{ foo.defaultVariant.purchasableId }}">
         {{ foo.title }} &ndash; {% if foo.defaultVariant.price == 0 %} Included with registration {% else %} {{ foo.defaultVariant.price|currency(cart.currency) }}{% endif %}
         </option>
    {% endfor %}
</select>
<input type="hidden" name="items[2][qty]" value="1">

Which also works well, but if the user does not choose an option, because I am passing a value of 1 with the hidden input, I get an error that I am attempting to use an invalid purchasable ID. Which also makes perfect sense.

I feel like I am so close, but just can't quite see clear enough to know what to do. Worst case I suppose I just listen for either a change/click event via javascript and update the qty value accordingly.

Thank you for any suggestions!

You definitely don't need JS here.

I'm  a bit pushed for time, so this won't be an epic answer, but e.g. with your select, you should not be using a hidden field for the qty.

The select itself just sets the quantity value - either 1 if the option is chosen or no value if the option is not chosen....it really is as simple as:

<form>

  {# primary item - use whatever input you like for qty, or just do it in a hidden... #}
  <input type="hidden" name="items[9999][purchasableId" value="{{ mainproduct.purchasableId }}">
  <input type="hidden" name="items[9999][qty]" value="1">

  {# accessories #}
  {% for accessory in accessories %}
    <input type="hidden" name="items[loop.index][puchasableId]" value=="{{ accessory.purchasableId }}"
    <select name="items[loop.index][qty]">
      <option value="1">Yes Please</option>
      <option value="0">No Thanks</option>
    </select>
  {% endfor %}

</form>

This will cause the following to be posted -
items[0][purchasableId] = 45

and depending on the user choice, either

items[0][qty] = 1 or items[0][qty] = 0

...and multiAdd will just ignore this if the qty = 0.

The key thing to understand is the value of the index is totally irrelevant as long as it is the same for the purchasableId and the qty - it just acts to join the data together - you could literally send:

items['TrumpIsInsane'][purchasableId] = 45
items['TrumpIsInsane'][qty] = 1

...and it should still work.  So for the primary product I just use something like 9999 so that I am sure it won't conflict with any of the loop indexes (I'm not going to have 10000 accessories eh?) -> it's just a made up number.

For completeness, radios would only be slightly different:

<form>

  {# primary item - use whatever input you like for qty, or just do it in a hidden... #}
  <input type="hidden" name="items[9999][purchasableId" value="{{ mainproduct.purchasableId }}">
  <input type="hidden" name="items[9999][qty]" value="1">

  {# accessories #}
  {% for accessory in accessories %}
    <input type="hidden" name="items[loop.index][puchasableId]" value=="{{ accessory.purchasableId }}"
    <input type="radio" name="items[loop.index][qty]" value="1" checked> Yes Please

    <input type="radio" name="items[loop.index][qty]" value=""> No Thanks

  {% endfor %}
</form>


What is the difference between the Translation Methods when creating a new site I am creating a new multi-lingual site and the documentation does not explain the difference between the options in the translation method dropdown.

What is different for each of these and when is it recommended to choose the from the options?

Not translatable
The field will always have the same value for each site
Translate for each site
Easy: the field can have a different value for each of your sites. Create 10 sites, all can have different content
Translate for each site group
Every site group can have a different value, create 10 site that are all in the same group, all elements will have the same value, create a site in another group -> that one can have a different value than the other 10
Translate for each language
Create 10 sites, all in the same language, all will have the same content, no matter what group they are in. Create another site in another language  -> this one can have different content
Custom
You can define custom behaviors
edit  a few more words about this
There will appear an <input>below that option and Craft will actually do this
if ($field->getTranslationKey($siteElement) === $field->getTranslationKey($element)) {
    // Copy the master element's value over
    $siteElement->setFieldValue($field->handle, $element->getFieldValue($field->handle));
}

Which basically means: it will render both object templates (the original element, and the element for all other sites) and injects the element into the template..
For example if you have something like { title } in your template, Craft will render those templates, and will compare them. If the titles are the same, the field is translatable and may contain a different value for all sites, if the titles are equally, the content of your field will be equally as well.


Error: "Variable "entry" does not exist" on basic template I'm new to Craft and I'm stumbling at the first hurdle for Craft 3

I'm getting "Variable "entry" does not exist." and I'm certain it's something so simple I'm missing.

Case:

Install craft 3 via composer
Add a Single section called "Homepage" (URI: "/" | template: "index")
Add "templates/index.twig" - test it with basic markup; displays correctly
Add plain text field to homepage section ("homepageHeader")
Fill out homepageHeader in control panel and save.
Change template to literally only "{{entry.homepageHeader}}"
Error above after page refresh

I must be missing something VERY simple. What is it?

In order to set an entry as your "homepage" entry you have to leave the uri in the section completely blank. It does not work when you insert a / because this route does not fetch the correct element thus Craft is not able to provide the entry variable in your twig template


How do I search craft.entries with multiple parameters? I'm filtering entries based off a searchbar with multiple parameters, and I'm building up an entries filter based off of them. Everything works great except for having more than one .search functions.

{% set req = craft.request %}

{% set results = craft.entries.section("properties") %}

{% set params = ['location', 'min-price', 'max-price', 'status'] %}
{% set query = {} %}

{% for param in params %}
  {% set key = param | camel %}
  {% set value = req.getParam(param) %}
  {% set query = query | merge({ (key):(value) }) %}
{% endfor %}

{% if query.location %}
  {% set results = results.search(query.location) %}
{% endif %}

{% if query.minPrice or query.maxPrice %}
  {% set min = query.minPrice ? query.minPrice : '' %}
  {% set max = query.maxPrice ? query.maxPrice : '' %}
  {% set results = results.search("price:" ~ '500000') %}
{% endif %}

{% if query.status %}
  {% set results = results.search('statusCategory:' ~ query.status) %}
{% endif %}

{% for entry in results %}
...

I've removed the whole min/max part just to simplify things, but it seems that if there is both a location and min/max price parameter, whichever one is last overrides the first. How can I combine these search parameters?

100% untested, but try something like this.

You're basically creating an array of all of your search criteria, then joining them into one .search() call at the end as a string separated with a space.  That's because Craft does "and" searching with multiple terms by default.

{% set req = craft.request %}

{% set results = craft.entries.section("properties") %}

{% set params = ['location', 'min-price', 'max-price', 'status'] %}
{% set query = {} %}
{% set search = [] %}

{% for param in params %}
    {% set key = param | camel %}
    {% set value = req.getParam(param) %}
    {% set query = query | merge({ (key):(value) }) %}
{% endfor %}

{% if query.location %}
    {% set search = search|merge([query.location]) %}
{% endif %}

{% if query.minPrice or query.maxPrice %}
    {% set min = query.minPrice ? query.minPrice : '' %}
    {% set max = query.maxPrice ? query.maxPrice : '' %}
    {% set search = search|merge(["price:" ~ '500000']) %}
{% endif %}

{% if query.status %}
    {% set search = search|merge(['statusCategory:' ~ query.status]) %}
{% endif %}

{% if search|length %}
    {% set results = results.search(search|join(' ') %}
{% endif %}

{% for entry in results %}
    ...


How to create custom field type in Craft 3 I have been struggling to create my own custom field, so I would like to ask how to create it.

First of all, I don't know where the files should be in.
I have some custom fields in Craft 2.
It might be able to be migrated, but it is not.

I have these files under src folder in a plugin.

fields/{fieldtypeName}FieldType.php
templates/_fieldtypes/{fieldtypeHandle}/input.html
templates/_fieldtypes/{fieldtypeHandle}/settings.html

Then I added a registration as the documentation, but Craft says it is not found.
https://docs.craftcms.com/v3/extend/field-types.html

In order to include a custom field type you first need to register your own module or plugin you can create the basic structure for both from pluginfactory.io and register them as you like. There is also a default module that comes with every Craft 3 installation. You only need to bootstrap it in your app.php

Then in your module you need the following code

public function init()
{
    Event::on(Fields::class, Fields::EVENT_REGISTER_FIELD_TYPES, function(RegisterComponentTypesEvent $event) {
        $event->types[] = MyField::class;
    });
}

And your class could look like the Incognito Field for example.
Basically every field has several methods implemented in the FieldInterface such as getInputHtml to render the HTML or normalizeValue to create a field value based on user or DB input and serializeValue to prepare the value for your DB. The interface has everything you need.

A good example to get started is to extend the PlainText field and customize it's functions. You can overwrite the inputHtml function and render a custom template

public function getInputHtml($value, ElementInterface $element = null): string
{
    // Get our id and namespace
    $id = Craft::$app->getView()->formatInputId($this->handle);
    $namespacedId = Craft::$app->getView()->namespaceInputId($id);

    // Render the input template
    return Craft::$app->getView()->renderTemplate(
        'module-id/fields/hidden/_input',
        [
            'name' => $this->handle,
            'value' => $value,
            'field' => $this,
            'id' => $id,
            'namespacedId' => $namespacedId,
        ]
    );
}


Craft CMS module composer dependancy After some research surrounding this I can't seem to fix this issue. So for a project I made a simple module with some variables that simply has to make an OAuth1 call and return some data.

The provider of the website advised me to use :

https://github.com/thephpleague/oauth1-client

So in my module I initialised another composer.json and required the package above. It gets correctly installed to the vendor map in my module. However whenever I call the new OAuth() or new OAuth1() it can't be found.

I've tried adding it while using the packagepath in the top of my module.php as well as my moduleVariable.php but to no avail. I was wondering if I'm doing something wrong? Or forgetting something? What's the best way to add composer libraries to your own custom module?

Best regards!

The easiest way around this is to include the required library in your main-project composer.json and let it handle it rather than your modules composer.json.

The alternative is to require your module properly in your main composer file as you do with plugins and install it via path which kinda breaks the idea of it


Is there a way to treat variants in a similar way as products? I'm trying to figure out if there's a way to either treat product variants as ww.site.com/product/variant or pass variables from a variant list (for example thumbnails that click to product and passes along variables for the layout of that page). Any takers?

I'm assuming it would be better to create a category > sub-category > product. Just would be great to have the same product information but be able to point to .com/pillow/green whilst returning the same basic product information.

Put simply, if you define the url for your product type as, say,

products/{categories.first().slug}/{slug}

...then if you visit this url (products/pillows/my-pretty-pillow) you would perhaps loop through and show all variants.

When they hit a url like products/pillows/my-pretty-pillow/green (to make this url work you'd need to define a route to point at the same template I think -> products/pillows/*/*)

....then you can simple look at craft.request.getSegment(4) and use that to determine which specific variant to show at that url.

(This is  much the same question actually:
How do I select a specific product variant by element/field/entry?)


Image Transform Internal Server Error (500 code) after Craft CMS update I just updated an "older" Craft site (version 2.4.2702) to the newest update (version 2.6.2958).

But now all my image thumbnails in the back-end are missing and if I upload any new assets, the thumbnail is not generated and I get a Internal Server Error 500 on the front-end as the URL it points to is still the cpresources/transforms/283?x=qFc4lFWR5 kind of URL.

The image thumbnail itself is also not generated anymore in the folder it is supposed to go in. I didn't change any folder permissions (only updated the new app folder ofcourse with the correct permissions). I'm able to upload assets so the permissions should be fine I guess.

I've had issues like this before, but those were resolved, so I don't know what is causing this issue again. Is there anything I forgot about this update that I needed to change? I needed to do a manual update.

The logs I get are these:

2017-01-17 10:13:26

Level   info
Category    application
Message [Forced] Finished task 14 (GeneratePendingTransforms).
2017-01-17 10:13:26

Level   info
Category    application
Message [Forced] Starting task GeneratePendingTransforms that has a total of 0 steps.

UPDATE

I do get a PhP error:

[18-Jan-2017 14:04:07 UTC] PHP Fatal error: Call to undefined method Imagine\Imagick\Imagick::getImageAlphaChannel() in MY-BASE-PATH-HERE/craft/app/vendor/pixelandtonic/imagine/lib/Imagine/Imagick/Imagick.php on line 191

But through the PhPInfo in the Craft CP I can see that Imagick extension 2.2.2 is installed with ImageMagick 6.7.2-7, so according to this page the method should exist: http://php.net/manual/en/imagick.getimagealphachannel.php.

UPDATE 2

As I dumbly clicked "rebuild all asset indexes" on the live site (instead of on the local development site in the browser tab next to it aaargh) I quickly added 'imageDriver' => 'gd', to the config as a workaround.

More a workaround than a solution but I added

  'imageDriver' => 'gd'

 to the config so it didn't use Imagick anymore. Works as supposed to now.


DevMode Class 'Exception\RuntimeException' not found We started getting this error inconsistently on our site, and now it's constant unless we turn devMode off. We have no idea what may be causing it, but it only happens on one page. With devMode turned off, this page loads as intended with no issues. Here's a stack trace of what's coming through:

Class 'Exception\RuntimeException' not found
/craft/app/framework/vendors/zend-escaper/Escaper.php(321)
/craft/app/framework/vendors/zend-escaper/Escaper.php(182): Escaper->toUtf8("[11:24:06.471][trace][system.db.CDbCommand] Executing SQL: UPDAT...")
/craft/app/framework/web/helpers/CJavaScript.php(35): Escaper->escapeJs("[11:24:06.471][trace][system.db.CDbCommand] Executing SQL: UPDAT...")
/craft/app/helpers/LoggingHelper.php(51): CJavaScript::quote("[11:24:06.471][trace][system.db.CDbCommand] Executing SQL: UPDAT...")
/craft/app/templates/logging/log-firebug.php(46): Craft\LoggingHelper::processFireBugLogEntry("trace", "11:24:06.471", "system.db.CDbCommand", "Executing SQL: UPDATE `craft_budhub_spend_analytics` SET `id`=:y...", ...)
/craft/app/framework/logging/CWebLogRoute.php(52): Craft\WebLogRoute->render("log", array(array("Loading "cache" application component in /var/www/thisisbud.dev/...", "trace", "system.CModule", 1499945046.3493, ...), array("Loading "path" application component in /var/www/thisisbud.dev/c...", "trace", "system.CModule", 1499945046.3495, ...), array("Loading "request" application component in /var/www/thisisbud.de...", "trace", "system.CModule", 1499945046.3497, ...), array("Serving "usePathInfo" from cache in /var/www/thisisbud.dev/craft...", "trace", "system.caching.Craft\FileCache", 1499945046.3501, ...), ...))
/craft/app/framework/logging/CLogRoute.php(104): CWebLogRoute->processLogs(array(array("$_COOKIE=array ( 'ccc7c40e11a9bcf94cb9cc672f7748a0username' =>...", "info", "application", 1499945046.3467), array("Loading "cache" application component in /var/www/thisisbud.dev/...", "trace", "system.CModule", 1499945046.3493, ...), array("Loading "path" application component in /var/www/thisisbud.dev/c...", "trace", "system.CModule", 1499945046.3495, ...), array("Loading "request" application component in /var/www/thisisbud.de...", "trace", "system.CModule", 1499945046.3497, ...), ...))

A few points that may help:

We are accessing and saving (encrypted) binary data to the DB, though we do this elsewhere on the site without issue.
The twig being loaded loads other pages too, which all run fine seperately
DevMode turned off, we can't see anything that's not working, but with devMode on, it's impossible to get past said error.

We've been wrestling with this for a while without any luck. Any help would be greatly appreciated!

Definitely agree with the comments that you should enable devMode from day one when working on a project. In addition, coding defensively can help avoid common frontend errors as well.

There's more on this topic in the article Handling Errors Gracefully in Craft CMS


List Entries in a section that are referenced as a relation in another I have a list of entries and I would like to filter them into 2 lists.

Entries that have been made a relation in another section
Entries that have NOT been made a relation in another section

I thought about tackling this the other way round and listing the section with the relations but some entires are related multiple times, so and the titles in the list get repeated multiple times. Unless this can filter out the duplicates, but it starts to get messy at this point.

Ideas welcome thanks.

You could use the without filter for this:

{% set entryParams = {
    section: mySection1
} %}

{% set relationParams = {
    sourceElement: mySection2,
    field: myEntriesField
} %}

{% set entriesWithRelation = craft.entries(params).relatedTo(relationParams).find() %}
{% set entriesWithoutRelation = craft.entries(params)|without(entriesWithRelation) %}


Complete working example for adding Craft Commerce items to the cart using AJAX and jQuery? I'm using Craft Commerce and every time I click the Add to Cart button for a product, I'm redirected to the Cart page. This works okay, but I'd like to use AJAX (with jQuery v1.12.4) for this to save being redirected to the Cart page.

I'm not great with JS though, so I was trying to find a complete working example for this in the demo templates get me started but I couldn't find one. I did find a similar question on here, but I don't think that's a complete working example as when I tried putting the JS from that example in my own functions.js file, I was getting a syntax error, so this is why I'm asking my own question. Thanks in advance for any help.

Here's what I'm using to show how many items have been added to the cart in the header:

{% set cart = craft.commerce.cart %}
({{ cart.lineItems|length }}) Items

Here's the markup I'm using for the current non-AJAX add to cart form:

{% for product in products %}

  {% for purchasable in product.variants %}

    <form method="POST" id="addToCartForm">

      <input type="hidden" name="action" value="commerce/cart/updateCart">
      <input type="hidden" name="redirect" value="basket">
      <input type="hidden" name="purchasableId" value="{{ purchasable.purchasableId }}">
      {{ getCsrfInput() }}

{{ product.title }}

{{ purchasable.price|commerceCurrency(cart.currency) }}

      <input name="qty" type="number" min="1" value="1">

      <input type="submit" value="Add to Cart" />

    </form>

  {% endfor %}

{% endfor %}

Here's my functions.JS file (i.e. empty after getting nowhere with other examples that I was trying to cobble together):

$(function() {

});

The question you link to - that is a working example really except you a) might not need the CSRF stuff if you haven't turned on CSRF protection (you should, though) - and of course the ... at the end means you should at least finish off the function and do some error handling.

In any case, in this specific case, you should just in essence need:

$(function() {

    $form = $("#addToCartForm");

    // handle submits via ajax

    $form.on('submit', function(e) {

        //Prevent the default submission
        e.preventDefault();

        //Get the form data
        var form_data = $form.serializeArray();

        // ajax it over to the server
        $.ajax({
            type: 'post',
            url: '/',
            data: form_data,
            success: function(response) {
                if (response.success) {
                    alert(response.cart);
                }
                else {
                    alert("Failure!");
                }
            }
        });
    });

});

..although I am doing this on my phone.  So if you get syntax errors let me know!


Limit Structure Depth Is it possible to limit the number of levels within a Structure element?

Let's say for example, I only want to max of two levels. So there can be only have something like the following with no way to allow a child of a child so to speak:

Parent

Child
Child

Parent

Child

Parent
Parent

Go in to the structured section's settings (Settings->Sections->Structure Name)) and set the "Max Levels" property.


Edit select dropdown field in a Matrix on the front-end Having a front-end user form where users can maintain there profile. I managed to get the single text and date field in the Matrix to be edited from the front-end but having issues with the select dropdown fields in the form.

The select dropdown is build up correctly but selected values won't save, in fact the existing value is cleared after submitting the form.

<form method="post" accept-charset="UTF-8">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="users/saveUser">
    <input type="hidden" name="redirect" value="mijnduikteam/gegevens/{{ currentUser.username }}">
    <input type="hidden" name="userId" value="{{ currentUser.id }}">

    <input type="hidden" name="fields[userDivingCertification]" value=""

                        Type
                        Certificaat #
                        Datum</th

                    {% for block in currentUser.userDivingCertification.order('certificateDate desc') %}
                    <input type="hidden" name="fields[userDivingCertification][ {{ block.id }}][type]" value="certifications">
                    <input type="hidden" name="fields[userDivingCertification][ {{ block.id }}][enabled]" value="1">

                                <select class="form-control" type="text" name="fields[userDivingCertification][ {{ block.id }}][fields][certificateType][]">
                                {% for option in block.certificateType.options %}
                                <option {% if option.selected %}selected="selected"{% endif %} value="{{ option.value }}">{{ option.label }}</option>
                                {% endfor %}
                                </select>

                                    <input class="form-control" type="text" name="fields[userDivingCertification][ {{ block.id }}][fields][certificateNumber]" value="{{ block.certificateNumber }}" >

                                    <input class="form-control" type="text" id="datetimepickerCertificate" name="fields[userDivingCertification][ {{ block.id }}][fields][certificateDate][date]" value="{{ block.certificateDate| date('d-m-Y') }}" aria-describedby="basic-addon4" >

                     {% endfor %}

                <input role="button" class="btn btn-primary" type="submit" value="Wijziging bewaren">

    </form>

I was struggling with the same issue. Using your code I was able to get the select box to update by removing the [] at the end of your select name variable.

So this code wasn't working

<select class="form-control" type="text" name="fields[userDivingCertification][ {{ block.id }}][fields][certificateType][]">

but changing to

<select class="form-control" type="text" name="fields[userDivingCertification][ {{ block.id }}][fields][certificateType]">

got it submitting correctly.

The other issue I was having with the data being wiped completely was due to the hidden type field not having the correct value. I had copied some code from elsewhere and forgot to change the value. Once I got it matching my Matrix Block Type handle it worked fine.


How to use sprite sheets effectively and responsively in Craft I'm planning for a site which will use a number of small image elements, which leads naturally to looking for first-load speedups by using sprites.

Since the site will be responsive, it will need the sprites to resize.

One way would be to let Craft do the resizing; might work well enough.
the offsets would also be very nice to find re-aligned with the resized sprite locations. I think I am probably talking about a feature request here. Maybe it could be as simple as a conversion function, cached results or not.
another possibility would be to allow Assets to specify their own non-generated images for given Transform labels. Maybe by a middle-extension that named the tranform, if not a tranform folder solution?

Ok, I think this is all dreamland for now, but might spark some thinking. I'm considering it because I think I'm realizing that the delay times for later than first images which show even on a Pingdom are probably due to limited sockets for browsers, or a modeled equivalent in the monitoring service if they are not just using Webkit contents for this.

Something to think about, or if someone has an answer I don't know about.

I thought I'd just add my two cents, since no one has answered this yet. :)

It's not clear from your question if these image elements are purely front-end design assets, or if the client/end-user needs to update them from within Craft.

In the case of front-end assets, my opinion is that how these are used in your site is part of the projects build phase, and not something Craft should be responsible for. If Craft starts implementing support for generating sprite sheets, there're tons of other front-end stuff that would be just as relevant to add. Compiling SCSS/LESS/Stylus, concatenation and minification of CSS and JS, building web fonts from SVG files, minification of images and SVGs, etc. I don't feel that this is what P&T should spend their valuable time on. :)

There are numerous ways to automate building a sprite sheet as part of the build, I use grunt-spritesmith which also gives me a complete stylesheet with classes for all the different elements.

If the problem is that the client needs to update the assets, I see why the sprite sheet has to be generated by Craft. It would be possible to make a plugin that creates a stylesheet from all images in a folder, a list of images or something like that. It would probably involve a lot of inline css, since you wouldn't know the sizes and positions of the different elements in advance.

But, depending on the nature of the elements I'm not sure if I think it's worth it.  Since you're considering making a sprite sheet I guess that the elements isn't actual content (ie images that should be accessible, searchable by Google, etc)? In that case I think I'd just lazyload them if they result in too many requests. If the elements is actual content, combining them into a single image would really ruin accessibility, so that is a really bad idea anyhow.


Contact Form sent via Ajax with file upload returns 302 instead of 200 status code I’m using the Contact Form plugin to submit a form that can also upload files via Ajax. The problem ist that instead of a success (200) I get a status code of 302. But I receive the resulting mail properly.

Everything worked fine when I hadn’t set everything up for the file upload. I serialized the form data, expected json, success (200).

...
dataType: 'json',
data: $(this).serialize(),
...

But when I switched to this to enable receiving files, things went south (302):

const formData = new FormData(this.form);

$.post({
    url: '/index.php',
    data: formData,
    type: 'POST',
    cache: false,
    contentType: false,
    processData: false,

    success: response => {
        if (response.success) {
            this.showSuccess();
        } else {
            this.showError();
        }
    },
    error: (xhr) => {
        // FIXME: This is a workaround because for some reason Craft returns a 302, even though everything works
        //        fine. See stackoverflow question here and fix if there is a solution.
        if (xhr.status === 302) {
        this.showSuccess();
        } else {
        this.showError();
        }
    }
});

I’m on Craft 3.0.15 and set up SMTP in Settings -> EMail. I tried it locally (using MAMP) and on my hosted server. Both give me the 302.

Any hint would be much appreciated.

Cheers,
Mark

Solved it (finally).

First part of the problem (the 302 redirect) was this missing configuration in the ajax call:

$.post({
  // ...
  dataType: 'json',
  // ...
};

It tells the server what you expect to get back from it.

Now this was fine, but I ran into a second issue. The xhr request stalled in Safari. When that happend and I reloaded the page (causing the request to finally stop), the email was sent anyways. The reason:

Safari seems to have an issue with this:

const formData = new FormData(formElement);

I found a hint here https://stackoverflow.com/a/8797289/2342963 that fixes the issue: appending the data manually to the FormData instance instead of passing the form element to the constructor.

So this is the working code:

const formData = new FormData();

$.each($('input, textarea, select'), function(i, element) {
    if (element.files) {
      $.each(element.files, function(i, file) {
        formData.append(element.name, file);
      });
    } else {
      formData.append(element.name, element.value);
    }
});

$.post({
    url: '/',
    data: formData,
    type: 'POST',
    cache: false,
    contentType: false,
    processData: false,
    dataType: 'json',

    success: response => {
        if (response.success) {
        // Show success
        } else {
        // Show error
        }
    },
    error: () => {
        // Show error
    }
});

Turns out, it wasn’t a Craft issue after all ¯_(ツ)_/¯


How to link to prev/next entry depending on related data? I am quite new to Craft and I am not sure how to get a prev/next link only for entries with related data in a specific field.

My situation:
I have a Structure (let's call it sourceEntry) with an optional field (can be empty or can have related data, let's call this one relatedData). That field is of type entries. So sourceEntry is related to other entries (I'll call them targetEntry).

Assuming I am on the entry's detail page (so, my sourceEntry object is just accessible via entry in my twig template) I would do this to link to previous/next entry:

{% set criteria = {section: 'sourceEntry' } %}
{% set prev = entry.getPrev(criteria) %}
{% set next = entry.getNext(criteria) %}
{# …and then just insert the links… #}

But in my case I need to get the prev/next entry that has set relatedData respectively I'd link to the prev/next entry that is related to targetEntry.

Example:
I have five entries of type sourceEntry: A, B, C, D, E.
The relatedData field for two of them is empty: B, C.
The others are related to posts of type targetEntry: A, D, E.
When loading the detail page for A there should be a next link to D, on detail page for D there should be a next link to E and a prev link to A and so on.

How am I able to achieve this? Thanks in advance!

EDIT:

This is the solution for those who are too lazy to click the link in Bob Olde Hampsink's answer:

{% set criteria = {section: 'sourceEntry', relatedTo: craft.users } %}
{% set prev = entry.getPrev(criteria) %}
{% set next = entry.getNext(criteria) %}
{# …and then just insert the links… #}

I feel kind of dumb now not even been trying this on my own before (although I knew about relations, but I wasn't sure how to set the criteria object properly). Thanks, Bob Olde Hampsink!

Add the relatedTo param to your criteria


Google Maps Plugin return coordinates I just need to return the latitude and longitude of my Google Maps marker.  I do not want to make a request to Google, nor do I need to display a map with javascript.  I need to create markers inside of blog entries and only return the coordinates.

Can the Google Maps plugin do this?  Can I pass the lat and lng to text fields when i save the entry?

Was out of town so couldn't answer this question until now. With Google Maps for Craft you can do so like this:

{% set marker = entry.yourMapField.getMarker(0) %}

{{ marker.lat }} {{ marker.lng }}

Or you can loop through all the markers on the map like this:

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

    {% for marker in entry.yourMapField.getMarkers() %}

        {{ marker.address }}<br>

    {% endfor %}

{% endfor %}

https://github.com/objectivehtml/Google-Maps-for-Craft/wiki/Getting-Address-From-Map-Markers


Q: Freeform - have users update form on the frontend I was wondering if it is possible to have users update their own entry on the front end with the Solspace Freeform plugin.

I get as far as getting all the necessary data of the user (freeform.submission) in a form (freeform.form) and I have added an input with the id of the entry to the form:
<input type="hidden" name="id" value="{{submission.id}}" />

When submitting this form it will save the data, but as a new entry instead of updating the existing one. So is there a way to update the existing id, similar as to what is happening in the cp?

Thanks!

I was able to find a solution. It's probably not the best way to go, but it works.

In the form add a new action: <input type="hidden" name="action" value="freeform/submissions/save"> which will override the standard action. It's the same form action Freeform uses to save entries in the CP.

Then add the id you want to update as value=.
For example:
<input type="hidden" name="submissionId" value="{{submission.id}}" />

One disadvantage is, is that this POST does not support the handle, values,.. input data for the fields - you need to use the fields id. So
<input name="{{ firstName.handle }}" value="{{ firstName.value }}" >
becomes
<input name="field_1" value="{{submission.FirstName}}" />

You can find the field id in the CP. Some fields might need a bit more info, like email is field_3[].


Problem with Pulling Event Entries The following code is throwing an error for me.

{% set eventEntries = craft.entries.find({
    section: 'events',
    event_startDateTime: '<= {{ now }}',
    limit: '4'
}) %}

{% for entry in eventEntries %}

Fatal error: Call to a member function getTimestamp() on a non-object

What I'm trying to do is pull 4 events where a date field (event_startDateTime) is before the current time.  My suspicion is that the {{ now }} variable isn't parsing inside the single quotes, but I'm not entirely sure.  Can anyone correct my code?

In Twig, you'll never need to double up on your curly brackets.  I.E.

{{ {{ }} }}

or

{% {{ }} %}

Change this (which is already inside of {% %}:

event_startDateTime: '<= {{ now }}',

To use string concatenation like this:

event_startDateTime: '<= ' ~ now,

And you should be set.


Plugin add options to entry edition What I'm trying to do is add two checkbox in the entry edition page, just under the dates or special notes, somewhere here :

Then if the checkbox is checked, I check it with an event and perform an action. But I dont know how to display my two checkboxes, I know it's all about the hook but I can't find the one.

Any advices ?

Well I found the way lurking into source code. You can see a

{# Give plugins a chance to add other panes here #}
{% hook "cp.entries.edit.right-pane" %}

Even though this hook is not listed in official documentation, you can access using the craft()->on() syntax, so I did this inside my plugin class :

public function init() {

    parent::init();

    craft()->templates->hook('cp.entries.edit.right-pane', function(&$context) {

        // do stuff here
    });
}


Craft 3 update failure i wanted update a new installed craft3 and got this message:

I took a look in the web.log file. The first line from today gives an error:
2018-04-25 03:39:23 [85.7.133.198][-][-][error][yii\base\InvalidConfigException] yii\base\InvalidConfigException: Unsupported DB driver value:  in /home/velolade/craft3/vendor/craftcms/cms/src/config/DbConfig.php:187

What's wrong here?
Thank you in advance for help!

The original poster solved this in a follow-up comment:

  After checking the log file - see my other question -, i activated the php functions "proc_open" and "proc_close" at my hoster's php settings and it worked. I'm not sure if i can leave these settings.

proc_open and proc_close are required if you want Craft 3 to automatically backup your database because it uses the native mysqldump and pg_dump binaries to perform the backup.

If, for whatever reason, you can't enable those methods, your options are to:

Set the backupCommand config setting to false. This will prevent Craft from performing database backups and you'll be responsible for manually creating them.
Set the backCommand config setting to some other script or service that can perform a backup without using those disabled methods.  Craft will respect whatever is set in this config setting.


compiled_templates folder using up inodes on Ubuntu 14.04 Server My server has gone down twice in the last 3 weeks because of an excessive number of files being created in the compiled_templates folder. This causes all of the inodes on our server to be used up causing the site to crash.

We previously thought this may have been because of a security test that hit multiple URLs on the site and generated too many templates. The original question can be seen here Security test generated large compiled_templates directory, site outage

This time there was no unusual traffic spike, so I can't assume it was because of the security testing. The only common thread seems to be that garbage collection is either not deleting the old compiled templates or craft is mis-configured. Any insights into this issue would be much appreciated.

EDIT: Looking in the compiled_templates folder it seems there are a few hundred different folders with names like 00 a9 b3 ... and inside those folders are sometimes hundreds of PHP files. I can't track down what templates some of them go to. For example one of the comments up to reads: /* __string_template__cc8a06d92434271d04fe341ad237b568da4c65f004cfec4d1fc576ee4e9b6c4a */

They have functions that echo out single lines of text, these functions are called doDisplay. I am not the original author of this site and am not an expert at Craft. I appreciate the help.

How many files are in the compiled_templates directory? There should be a 1:1 correlation between the number of actual templates you have, and the number of cached .php compiled templates in the compiled_templatesfolder.

It shouldn't have anything to do with 404 errors, etc.

I've never seen nor heard of the situation that you've described.


How to get field values from Global Set using Element API plugin? I'm pulling data from a Global Set using the Element API plugin and am wondering if there's a cleaner way to write the transformer function?

My craft/config/elementapi.php file looks like this:

<?php
namespace Craft;

return [
    'endpoints' => [
        'api/settings' => [
            'elementType' => 'GlobalSet',
            'criteria' => ['handle' => 'siteSettings'],
            'first' => true,
            'transformer' => function(GlobalSetModel $siteSettings) {
                return [
                    'defaultTitle' => $siteSettings->getContent()['defaultTitle'],
                    'defaultDescription' => $siteSettings->getContent()['defaultDescription']
                ];
            },
        ],
    ]
];

Thanks in advance!

There’s no need to go through getContent() to access your field values; you can access them directly from the GlobalSetModel:

'transformer' => function(GlobalSetModel $siteSettings) {
    return [
        'defaultTitle' => $siteSettings->defaultTitle,
        'defaultDescription' => $siteSettings->defaultDescription
    ];
},


Using a variable with Twig include I am trying to use a variable, based on an entry field, to load a form with a Twig include. The code is pretty straightforward:

{% set theForm = entry.formSelect %}
{% include theForm %}

Doing this throws this error:

  Undefined property: Craft\SingleOptionFieldData::$cacheKey

If I print the variable, it looks exactly as you would expect, e.g. forms/_basic

Any suggestions would be appreciated!

You need to let Twig interpret the variable as a string. This works for me:

{% set theForm = entry.formSelect %}
{% include ''~theForm~'' %}

Hope this helps!


Does it make sense to cache a Global? I have a global that consists of 1 rich text field and the content is displayed on every page. Does it make sense to cache that? If so, I am assuming it should be cached globally?

It all depends on what your template is doing with the global.

If it's doing something to cause multiple database calls, then yes, you'll probably see some improvement (maybe minuscule, maybe more significant).

Anywhere you use a cache tags brings an overhead of one additional database call, so you just need to make sure it's worth it.


Feed Me import from CSV ignores decimal point I use Feed Me to import values from a .csv file into my entries. Since a day i have an issue i can't explain. I didn't change anything.
Precisely, the issue concerns a number field.
In the .csv file, i have, for example, the value 769.00.
Then i import this value with Feed Me and get the value 76900 in the number field. The decimal point gets ignored:

Here's the csv row:
Artikelnummer,Bestellnummer1,Artikelbezeichnung,Grösse,Farbe,Modelljahr,Notiz,Warengruppe,Hersteller,VKbrutto,UVP,Lagerbestand,Reserviert,Bestellt

18128,S20TONR2716,Stevens Tonga 27.5" Disc Shim. Alivio 22 Gang,16",Fire Red,2020,,Mountainbike,Stevens Bikes,769.00,,1,0,0

It's the same problem as here: https://github.com/craftcms/feed-me/issues/443

My website language is: de-CH

Can anyone give me a hint where this issue comes from?

With the help of the Craft Support Team, i solved this problem for me.
Two ways to solve this:

Change Number field to text field.
Change Language under users/user/preferences/language from Deutsch to english.


Locale Global section in CP bringing back page can not be found I've been asked about doing a Russian version of a website. I've set up a new locale in the Locale settings, as well as an ru/ folder with index.php and .htaccess. Adding a news story in Russian works fine, though changing a Global section to Russian brings up a "Page Cannot be Found".

The address for this is http://example.com/admin/globals/ru/globals

Does this look right?

general.php:

return array(
    'omitScriptNameInUrls' => true,
    'siteUrl' => array(
        'en' => 'http://example.com/',
        'en_gb' => 'http://example.com/',
        'ru' => 'http://dropinn.net/ru',
    ),
);

/site/ru Folder:

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

// Tell Craft to serve the Russian content
define('CRAFT_LOCALE', 'ru');

All of your settings look fine.

Most likely what happened is that when you added the new Russian locale under Settings->Locales, the "Resave All Elements" task that needs to run either didn't get a chance to complete or just ran into an error and failed.

If you don't have any Russian content yet, try deleting the locale and re-adding it - making sure that the task in the upper right hand corner completes.  If you already have Russian content, temporarily add any new locale, let the task complete, then delete the temporary locale.  That will also fix it for the Russian locale.


Generating pending image transforms stuck My image transform task always gets stuck halfway through so that I have to "repair" the task as per this guide. Im trying to convert about 150 images (amounts to ~300 steps). Resetting the task within the database does work but it's not a permanent solution.

I've upped the php memory limit to 1024M, execution time is 0 and Apaches timeout is set to a ridiculously high number. Disk space is available and it's happening with imagemagick as well as gd. It also happens both on my local dev VM running Ubuntu 14.04 as well as on my Debian server. PHP and Apache error logs are empty on both machines. I'm running the Personal edition and the latest version of Craft.

I also tried to set ini_set('max_execution_time', 0); in craft/app/services/AssetTransformsService.php but it didn't change anything.

Some more info:

Some image transforms are missing after restarting the task until it's complete. That renders the workaround by resetting the task in the db basically useless because not all images are transformed by the time it's complete.
It's not a specific image that is preventing the task from completing, as it's always a different image that it's stuck on.
There are usually 75-85 images converted until it's stuck.
Update Asset Indexes doesn't help.
Clearing all caches makes Craft convert all images again. It doesn't delete the old files, it just overwrites them (and gets stuck, as usual).

I was having this issue (w/ PHP 5.6, Craft 2.6.x, on WebFaction hosting) because it seemed like PHP had no memory limit and single processes were handling huge image transform queues, bombing when it got over 1.5gb or so.

Making sure Imagick has a memory cap seems to do the trick to avoid the queue getting stuck as PHP runs out of memory, which is discussed here:

Possible memory leak - GeneratePendingTransforms/ImageMagick

Relevant code:

// From http://stackoverflow.com/a/12835966
// Pixel cache max size
$this->setResourceLimit(\Imagick::RESOURCETYPE_MEMORY, 256);
// Maximum amount of memory map to allocate for the pixel cache
$this->setResourceLimit(\Imagick::RESOURCETYPE_MAP, 256);

in craft/app/vendor/pixelandtonic/imagine/lib/Imagine/Imagick/Imagick.php at line 33, at top of smartResize() function.

Update:

If you are not on shared hosting but on a VPS (or otherwise have sudo access on your server, OR are able install ImageMagick + php-imagick from source), you can set memory caps for ImageMagick directly using a policy.xml file, e.g.:

<policy domain="resource" name="memory" value="1GiB"/>
<policy domain="resource" name="map" value="1GiB"/>
<policy domain="resource" name="area" value="1GB"/>
<policy domain="resource" name="file" value="768"/>


Users in odd state of pending and needing password reset Users are falling into the following state:

Tried to sign up with public registration
Never clicked or never received (or so they claim) the verification email.
Users try to sign up and email is already taken
Users cannot reset password as their account is not verified.

Is this a problem? Or am I missing something. Is there a way to activate when they click the reset password link email?

Apart from resending verification email manually for all 100+ users is there anything else i can do?

Yeah... sounds like a registration workflow issue.  If they click on the activation link and it's past the time it's valid, the page does have a link where they can resend it, but that's only going to be helpful if they got the email in the first place.

I think for now you'll have to use the "Resend Activation Email" button in the CP.


What search engine does Craft CMS come with? New to Craft CMS. Our corporate website has been built using Craft. When using the site search, it is not finding all pages within the site. Wondering what the search engine technology is and how to re-index or broaden. Also, not crazy about the search results (SERP) display. What customizations are available?

The Craft CMS documentation has some technical information about how searching works with the various Craft ElementTypes.

There is also documentation on setting up a search form.

If you're looking for a more complete and full-featured search solution, SquareBit's Search Plus is an excellent option.


How can I get a full stack trace in my custom plugin log? I'm using MyPlugin::log to separate the errors for my plugin. However, I'm only able to log a simple message using this technique.

Is it possible to have that output the full stack trace?

Here's what I'm getting (note the general format)...

2015/06/09 20:41:42 [error] [plugin] My example error message.
in /craft/app/etc/plugins/BasePlugin.php (65)
in /craft/plugins/businesslogic/services/BusinessLogicService.php (194)
in /craft/plugins/businesslogic/controllers/BusinessLogic_ActivitiesController.php (47)

But here's what I want (again, note the general format)...

2015/06/09 20:39:25 [error] [exception.CException] exception 'CException' with message 'Craft\BusinessLogic_ActivitiesController and its behaviors do not have a method or closure named "handleError".' in /craft/app/framework/base/CComponent.php:266
Stack trace:
#0 /craft/plugins/businesslogic/controllers/BusinessLogic_ActivitiesController.php(47): CComponent->__call('handleError', Array)
#1 /craft/plugins/businesslogic/controllers/BusinessLogic_ActivitiesController.php(47): Craft\BusinessLogic_ActivitiesController->handleError()
#2 /craft/app/framework/web/actions/CInlineAction.php(49): Craft\BusinessLogic_ActivitiesController->actionUpdate()

How do I get the #0, #1, #2, etc. to show up?

By default a full stack trace will only be assembled and logged if an exception is thrown (which is what you're looking at in your 2nd example) mainly for performance reasons - cycling through the backtrace and assembling all of that info is a relatively expensive operation.

Standard calls to MyPlugin::log or Craft::log will get a partial backtrace added to each message.  The depth of that is controlled by the YII_TRACE_LEVEL PHP constant, which Craft sets to 3 by default.

If you want to have them log deeper into the trace, set that to a higher number in your public index.php file, just be aware of the performance implications.

There is some discussions of that constant here in the Yii docs: http://www.yiiframework.com/doc/guide/1.1/en/topics.logging#logging-context-information


Pagination and "if" condition Some of my entries have the same entry.title. At the frontend, I would like to display these entries only once. This works with the following code:

{% set entries = craft.entries().section('produkte').relatedTo(category) %}
{% set existingtitle = [] %}
 {% for entry in entries %}
  {% if entry.title not in existingtitle %}
    {{ Display the Results }}
  {% endif %}
  {% set existingtitle = existingtitle|merge([entry.title]) %}
 {% endfor %}

My question is: How can I then paginate these results? For example 9 entries per page?
If I paginate before the "if" condition gives me not the required result.
Any help or tips are highly appreciated!

You can build an array of the filtered results, then paginate that.

{% set entries = craft.entries().section('produkte').relatedTo(category) %}
{% set filteredEntries = [] %}
{% set existingtitle = [] %}
{% for entry in entries %}
    {% if entry.title not in existingtitle %}
        {% set filteredEntries = filteredEntries|merge([entry]) %}
    {% endif %}
    {% set existingtitle = existingtitle|merge([entry.title]) %}
{% endfor %}

Then modify this code to paginate array: https://gist.github.com/juban/a55781d49f2f68ec3ca47979bcaaa49a


How to prevent Craft from injecting scripts in the page? I have a website that resides behind a static cache. Today, I realised that some of the cached pages contain this bit of JavaScript at the end:

<script type="text/javascript">
/*<![CDATA[*/
(function(){
    var XMLHttpFactories = [
        function () {return new XMLHttpRequest()},
        function () {return new ActiveXObject("Msxml2.XMLHTTP")},
        function () {return new ActiveXObject("Msxml3.XMLHTTP")},
        function () {return new ActiveXObject("Microsoft.XMLHTTP")}
    ];
    var req = false;
    for (var i = 0; i < XMLHttpFactories.length; i++) {
        try {
            req = XMLHttpFactories[i]();
        }
        catch (e) {
            continue;
        }
        break;
    }
    if (!req) return;
    req.open('GET', "https://allaboutberlin.com/index.php/actions/queue/run", true);
    if (req.readyState == 4) return;
    req.send();
})();
/*]]>*/
</script>

Since the page is cached, every page loads makes this HTTP request, and it could easily bring my website down if it gets a traffic spike. How do I disable this feature?

You can set the runQueueAutomatically config setting to false to prevent this.

You'll just want to set up an alternative way to process the queue as noted in the docs.


Updating a Users Join Date? I'm doing a big import of users from an EE install using the Import plugin. I can pull in all the details I need except the join date, so I looked at the craft db to see where it needs to be changed.

I successfully managed to change it by updating the craft_elements table, dateCreated column. This changed the join date in the control panel, however it does update the dateCreated column in the craft_users table so I updated there also.

Just wondering if thats correct?

Yup, that's correct. The craft_elements.dateCreated column is the one that is referenced by the user's Join Date.

For the sake of being thorough, I prefer to copy that same value into craft_users.dateCreated, just as you have done.


Imported entries showing wrong post date Anyone familiar with InstaBlog plugin? I need to import some entries (not Wordpress) and everything works fine except the published date for all entries is showing today's date. When I view the entries in the control panel, the post date for each entry is correct, but is displaying the wrong date on front end. The InstaBlog template uses this to display the dates

{{ blog.postDate.format('F d, Y') }}

Has anyone encountered this?

Try using the date Twig filter instead

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

If the post dates on your entries are stored as datetime objects then the above should work.


Commerce: Is there a way to use a countries dropdown with iso codes (US, CH etc) instead of ids? Here's some code from Craft Commerce's examples:

<form method="POST" accept-charset="UTF-8" class="ui form validate">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="commerce/cart/updateCart" />

    [...]

    {% set countries = craft.commerce.countries %}
    {% if countries|length > 1 %}

            {{ "Country"|t }}
            <select name="{{ modelName }}[countryId]" class="ui fluid dropdown">
                <option value="">{{ "Choose Country"|t }}</option>
                {% for country in countries %}
                    {% set optionValue = (model ? model.countryId : '') %}
                    <option value="{{ country.id }}"{% if country.id == optionValue %} selected="selected"{% endif %}>{{ country.name }}</option>

{{ country.name }}

                {% endfor %}
            </select>
            {% if model and model.getErrors('countryId') %}
                {{ model.getErrors('countryId')|join }}
            {% endif %}

    {% endif %}

    [...]

</form>

I wonder if it's somehow possible to work with the country code (e.g. US, CH...) instead of the country id of Craft Commerce (1..256). So basically, countryId vs. countryIso?

I can't find any information in the docs.

It might be a small detail, but when using form autofill with programs like 1password, it won't be able to fill in the country automatically when using an id vs. a country code.

This should do it:

{% set countries = craft.commerce.countries %}

{% for country in countries %}

{{ country.iso }}

{% endfor %}


After updating to Craft 2.5, standard and custom rich text (Redactor) fields disappear After updating to Craft 2.5, some rich text fields have disappeared from the CMS.

While this similar to the issue described here, the answer did not fully resolve my issue.

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

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

Version 1 formattingAdd syntax:

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

Version II formattingAdd syntax:

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


Installation stops halfway. Files not found and internal server error 500 I've installed craft on some terrible hoster (I know, under force). Because of that I had to install craft in the public folder, next to the index.php file. I've set the path to ./craft and activated the .htaccess file. Now it will show the installation page, but halfway stops
with the attached errors.

The odd thing is that it searches for /garnish-0.1.min.map in the site root, while it's in the app/resources etc folder?

(Click to enlarge)

EDIT: Placing the file garnish-0.1.min.map in the root removes the first error, apparently it's really looking for the files in that place?

The log file got me on my way after a tip from Brad Bell:

  'CDbException' with message 'CDbCommand failed during the SQL statement: SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'craft_assetfiles' already exists' in ...craft/app/framework/db/CDbCommand.php:358

Removing the database and doing a fresh install solved the issue.


loop trough whole array inside a field I want to write an entire loop into a field like this:

Obviously this is not working. What would be the correct syntax when twig is written inside a field?

Also is there a name for the twig tags inside a field? I have a hard time searching the interwebz for this.

You can by using this: {{ include(template_from_string(entry.fieldName)|raw) }}

You could also try it with just |raw But that probably only works for just HTML

This works on both a Plain Textfield aswell on a Richtext area. Although I wouldn't recommend putting code in your textfield's like that.

The original answer on a simular question can be found here: https://craftcms.stackexchange.com/a/1270/3848


Field name in reusable macro I'm creating a macro I'd like to reuse multiple times but the only thing that changes is the field name (matrix). Here's an example:

{% for block in entry.fieldname1 %}
<h3>{{ block.title }}</h3>

I'd like to increment this macro so I don't rewrite this code snippet over and over again but when I try and change entry.fieldname1 to a string it's no{% set string = entry.fieldname ~ 1 %} it is no longer recognized inside the for loop.

Any ideas?

Try using an array syntax instead of the object syntax:

{% set string = entry['fieldname' ~ 1] %}


Craft CLI RC1 Connectivity Issues with MAMP Pro I've been trying to run the new Craft CLI for the last couple of versions without any success. I figured maybe since we weren't at RC1 yet that it wasn't fully working. After seeing Ryan's video about it at https://mijingo.com/lessons/craft-3-command-line/ I realized that wasn't the case (and with RC1 being released today).

I am using MAMP Pro (like Ryan does in his video), but I have it using the standard MySQL port at 3306. I also have PHP 7.1 installed at the terminal through homebrew and pdo_mysql is a compiled in module. I am also using RC1.

Interestingly, if I use localhost I get a completely different message than if I use 127.0.0.1. But regardless, both still fail.

Which database driver are you using? [mysql,pgsql,?]: mysql
Database server name or IP address: [localhost] localhost
Database port: [3306] 3306
Database username: [root] root
Database password:
Database name: craft3
Database table prefix:
Testing database credentials... failed: SQLSTATE[HY000] [2002] No such file or directory

Which database driver are you using? [mysql,pgsql,?]: mysql
Database server name or IP address: [localhost] 127.0.0.1
Database port: [3306] 3306
Database username: [root] root
Database password:
Database name: [craft3] craft3
Database table prefix:
Testing database credentials... failed: SQLSTATE[HY000] [2002] Connection refused

If I create the database manually and put the credentials into my .env file everything connects just fine without any issue. Is there something else I should be considering?

I gave everything a try, but the only thing that worked for me was ensuring "Allow network access to MySQL" was ticked in MAMP.

Screenshot: http://c42.co/Ur30EJ


Image transform with focal point - in Element API I can call predefined image transforms no problem -

$image->getUrl('small')

but cropped mobile transforms need to use the image asset's set focal point (from the Image Editor). I can't find any example of how to use this feature in code?

I assume the only way to use this focal point is setting a new transform array in PHP? (i.e. the preset values are ignored).

Be good if there was an option to use the Image Focal point in the Transform setup (UI).

Focal Points apply to the Asset itself; that way the same Focal Point can be used with any transform, and it'll still keep the same point of interest centered when the image is transformed.

It should use the Focal Point automatically, you shouldn't have to do anything other than set it in the image editor.


Craft 3 redirect of existing and non-existing URLs I'm upgrading a relatively large, but low budget, local government website from Craft 2 to Craft 3. The major remaining pain point is a replacement for the Craft 2 Reroute plugin, which is not available in the Craft 3 Plugin Store.

The main use of Reroute was redirecting existing URLs to other URLs within the site (and against my preferences to external URLs as well). The site is built around a strong hierarchy and quite often the parent page of "section" is redirected to the first child page (because the parent page serves as a conceptual folder and has no content on its own). And because Reroute worked well old entries/pages were not always deleted, just redirected to their new location or replacement pages by the content editors.

In Craft 3 we have Redirect plugin, Retour and Sprout Redirect, but as far as I can tell they only redirect non-existing URLs.

Now I could add a redirect Entry field to the various sections, and manually manage it that way, but it is quite a lot of work in the midst of an upgrade done by one little person (me).

So have I misunderstood that there are no existing plugins that will redirect existing URLs? Or am I missing an obviously easy way of doing this?

Based on your comments, I'd recommend creating a new entry type in your section.

Create a "Redirect" entry type which only contains a URL link (or an Entry field) so the page knows how to handle the redirect. For any entries that need to be converted to a redirect, simply swap the entry type to use this instead.

Then you can simply map that entry type to a redirect template:

{% redirect entry.newUrl %}

I've done this, and it works well.


Problem with data hash only storing last entry in loop 1: I'm creating a data hash object and then looping through a collection of entries to store the results of various macros in it:

{% set data = {} %}
{% set people = craft.entries().section('people').all() %}

2: I'm setting a reference to each entry and then merging the content compiled into my data object:

{% for person in people %}
    {% set i = loop.index %}

    {# get and set key|values #}

     {% set data = data|merge({
        i: {
            "key": value,
            "otherKey":  otherValue
        }
    }) %}
{% endfor %}

3: And then I'm looping through my data object for output:

{% for row in data %}

        {{ row.key|raw }}
        {{ row.otherKey|raw }}

{% endfor %}

The structure of the output at stage 3 is fine, but it's only resulting in 1 row out of 45 people entries.

What am I doing wrong at 2 please?

For the hash key to be dynamic, you must wrap it in parentheses:

(i): {


Show error when normal user try to login in CP when I login to my Craft CMS website via a normal user that user doesn't have permission to login to the Control Panel, it displays some error like HTTP 403 – Forbidden – yii\web\ForbiddenHttpException.

This error is correct but I want to display some message instead of this error.

You are seeing this because you have 'devMode' => true, in your config/general try switching to false and should hit a 'user friendly' message


Can I create multiple website using the same admin control panel and what I have to change for that? I want to create the multiple website using Craft CMS existing control panel. I am using craft 3.x
Do I need the Craft Pro to use this feature?

Yes, you can create it. Follow below steps and create new website using same control panel.
You should go to Settings > Sites
You can create another website using same admin
Handle site at section level as per your requirement
Make required changes as mentioned below.

.env file in create environ variable.

Same variable use in config>generale.php file same as “dev”.

Admin side setting>site>change primary side which site you want to execute at front end

You don't need the Craft Pro for this feature. You can do that with Craft Solo as well.


Asset Uploading via Assets Field Broken, please help *Update: Installed MAMP Pro, reinstalled Craft, asset upload is working now. Not exactly a fix, but seemed like the simplest route of action due to my unfamiliarity with PHP. Thanks to those who responded to my question.

I'm a newcomer to web development and Craft CMS. I've downloaded and installed Craft CMS locally and I'm following along with an "Up and Running With Craft CMS" tutorial to get my bearings.

I am unable to upload assets via an asset field. The upload box appears and after selecting a file to upload the progress bar fills and freezes and the loading wheel spins on forever. Due to this I can't upload any images and therefore can't create my site properly. Please help!

Checking the logs is of course recommended:

craft/storage/runtime/logs

However, I have personally found that failed uploads are related to "write" issues where either the directory permissions are invalid or the actual upload path doesn't exist (aka invalid).

One simple way to potentially obtain more information is to look at the actual HTTP response for the "upload file" AJAX request. I often do this via Chrome's Developer Tools' Network tab.

Open Chrome Developer Tools
Click the "Network" tab.
Perform the file upload.
Click on the "uploadFile" request that was generated
Click the "Response" tab to view the completed response (which will appear once the response is returned).


How to update cart.lineItems while specifying HTTP cache headers? I use the following cache system, specified in the header of all pages:

{% set expiry = now|date_modify('+1 day') %}
{% header "Cache-Control: max-age=" ~ expiry.timestamp %}
{% header "Pragma: cache" %}
{% header "Expires: " ~ expiry|date('D, d M Y H:i:s', 'GMT') ~ " GMT" %}

This does not coexist properly with the variable {{ cart.lineItems|length }} which displays on each page the number of products currently in the cart.

When I update the basket and go back to a previously visited pages, the cart is not up to updated and retains the value displayed during the previous visit.

To be more specify: I do not use the {% cache %} tags on the template part which displays the shopping cart.

I do not think you can achieve this with browser caching - there's no concept of cache 'escaping' with this type of caching.  Indeed, there's currently no concept of cache escaping with Craft's {% cache %} tag either...which is a shame.

In general, even, caching at the page level when using Commerce carts is tough/impossible - e.g. you'll also need fresh CSRF tokens for cart operations etc.

Currently (without plugins anyway) - the best thing is probably to use Craft cache tags for static page elements and simply avoid caching things like your cart count and add to cart forms etc.  And put your site on a nice fast server :)


How to update from a very old version of Craft? I'm trying to update an old site that is still running on Craft 2.2 (from September 2014), but unfortunately the update process to the current version (2.6) breaks.

Does anyone have any experience of upgrading a Craft site from several versions back? I'm thinking my best bet might be to try doing it in a series of steps by downloading intermediate versions from here. I'm wondering though if there are particular version numbers that are good milestones for updating (or best avoided)? (I half remember a version that had to be manually installed a while back) Or alternatively, whether there's a better approach I haven't thought of?

Update: the problematic step seems to be upgrading to 2.5. I've managed to run updates up to the last build of 2.4 but the jump from 2.4 to 2.5 always seems to fail. The error message is just "There was a problem updating your database", so it's hard to know what exactly is going wrong.

Ok, after a lot of trial and error I've finally managed to get this site upgraded. Here's a rough outline of the process and what the problem turned out to be:

First, I tried updating one minor version at a time. This led me to find that the problem seemed to be with updating from the last build of 2.4 to the first build of 2.5
The error message on update wasn't super helpful ("There was a problem updating your database"), but by trawling through Craft's log file (craft/storage/runtime/logs/craft.log) I found that the update seemed to be failing when trying to create the table elementindexsettings because (for whatever reason) that table already existed (resulting in the error Failed to apply migration: m150827_000000_element_index_settings).
I can't think why this would be the case, since after each failed update attempt I fully restored my previous database, but since my elementindexsettings table was empty, I dropped it and tried the update again. At this point it worked.

So in summary, the solution was:

Update to Craft 2.4.2726 (and commit this to version control!)
Attempt a manual update to Craft 2.5.2750. When this fails, drop the elementindexsettings table and try running the update again (ie. go to /admin and press the "Finish up" button.
Update to the latest version.

As a side note, I found setting Craft's backupDbOnUpdate config setting to false made the update process much faster and less painful when having to do a lot of attempted updates followed by rollbacks (though obviously if doing this be careful to make sure you have a backup you can restore if the process goes wrong).


Modify Order table in Control Panel I need to add and/or change an attribute in the order table on /admin/commerce/orders.

The Order Element itself does not have a EVENT_SET_TABLE_ATTRIBUTE_HTML, and I've tried with variations like this:

public function init()
{
    parent::init();
    Event::on(Element::class, Element::EVENT_SET_TABLE_ATTRIBUTE_HTML,[$this, 'setOrderStatusTableAttributeHtml']);
}

public function setOrderStatusTableAttributeHtml($event, $attribute)
{
    if ($event->element instanceof \craft\commerce\elements\Order && $attribute == 'orderStatus') {
        return 'Changed';
    }
}

The event does not show up in the debug bar. I've also tried a EVENT_INIT with die('died') an that kills the execution, so my plugin is installed and loading.

I solved this by overriding the routes set by craft commerce and extend the OrderController and the Order element.

This is not a good solution (I'm going upload this as a plugin) and if several plugins overwrite the same route, only the latest plugin will work.

If anyone have a proper solution I'll accept that. I'll leave this answer here in the meantime.

Plugin::init()

    Event::on(UrlManager::class, UrlManager::EVENT_REGISTER_CP_URL_RULES, function (RegisterUrlRulesEvent $event) {
        $event->rules['commerce/orders'] = 'commerce-easy-order-management/orders/order-index';
        $event->rules['commerce/orders/<orderId:\d+>'] = 'commerce-easy-order-management/orders/edit-order';
        $event->rules['commerce/orders/action/<orderId:\d+>'] = 'commerce-easy-order-management/orders/order-action';
    });

controllers\OrdersController

class OrdersController extends \craft\commerce\controllers\OrdersController
{
    /**
     * Index of Orders
     * Overwriting commerce/controllers/OrderController::actionOrderIndex()
     *
     * @return Response
     * @throws \Throwable
     */
    public function actionOrderIndex(): Response
    {
        // Remove all incomplete carts older than a certain date in config.
        Plugin::getInstance()->getCarts()->purgeIncompleteCarts();

        Craft::$app->view->registerCssFile('https://use.fontawesome.com/releases/v5.3.1/css/all.css');

        return $this->renderTemplate('commerce-easy-order-management/orders/_index');
    }
}

elements\Order

class Order extends \craft\commerce\elements\Order
{
    /**
     * @inheritdoc
     */
    public function getTableAttributeHtml(string $attribute): string
    {
        if($attribute !== 'orderActions') return parent::getTableAttributeHtml($attribute);
        return 'MyActionHTML';
    }

    /**
     * @inheritdoc
     */
    protected static function defineTableAttributes(): array
    {
        $attributes = parent::defineTableAttributes();
        $attributes['orderActions'] = ['label' => Craft::t('commerce', 'Actions')];
        return $attributes;
    }
}

templates/orders/_index.html

{% extends "_layouts/elementindex" %}

{% set title = "Orders"|t('commerce') %}
{% set docTitle = title~' - '~'Commerce' %}
{% set elementType = 'MY_NAMESPACE\\elements\\Order' %}
{% set selectedTab = 'orders' %}
{% set selectedSubnavItem = "orders" %}
{% set bodyClass = (bodyClass is defined ? bodyClass~' ' : '') ~ "commerceorders     commerceordersindex" %}

{% do craft.app.view.registerTranslations('commerce', [
    "Total Revenue",
    "Last 7 days",
    "Last 30 days",
    "Last Week",
    "Last Month",
    "Custom Range",
    "Apply"
]) %}


Is there a way to hide Matrix blocks based on the Selected Entry Type? I have 2 primary entry types, one for a full width page, and one for a sidebar page. The sidebar page shares about 90% of the same block types as the full width page.  The other 10% do not apply to the sidebar page at all.

Instead of going to the trouble of duplicating (and maintaining) an additional Matrix set for the sidebar page, sans the non-applicable block types, I have decided to use the same Matrix for both pages.

I am looking for a way to disable / hide the unused block types on the sidebar page entry type. Just as with the normal fields which can be assigned or not to the entry types, shouldn't the matrix block types also work in the same manner?

Any ideas?

No. Matrix blocks do not work in that manner. However you define it in the field is how it'll show when you edit it. If it's really important not to show that block type you can write a plugin that checks for an entry type, and hide certain block types based on that result. Granted that's a lot of work for very little gain. You would be better off ignoring the unwanted block types or building a new matrix field.


Can random be used for ordering with related/assets, in cached code? I'm trying to determine if I can update this:

{% cache %}
[
{% set tags = craft.tags.group('color','season','style','venue').limit(null) %}
{% for image in craft.assets.relatedTo(tags).order('elements.dateCreated desc') %}
{% set thumbParams = {
    width: 300,
    height:300,
    mode: 'crop'
} %}
{% set smallParams = {
    width: 768,
    mode: 'fit'
} %}
    {
        "url": "{{ image.url }}",
        "filename": "{{ image.filename }}",
        "imageTitle": "{{ image.imageTitle }}",
        "imageThumb": "{{ image.getUrl(thumbParams) }}",
        "tagsColor": [
{% for tag in image.tagsColor %}
        {
            "slug": "{{ tag | slugify }}",
            "tag":  "{{ tag }}"
        }{% if not (loop.last) %},{% endif %}

{% endfor %}
        ],

        "tagsSeason": [
{% for tag in image.tagsSeason %}
            {
            "slug": "{{ tag | slugify }}",
            "tag":  "{{ tag }}"
            }{% if not (loop.last) %},{% endif %}

{% endfor %}
        ],

        "tagsStyle": [
{% for tag in image.tagsStyle %}
            {
            "slug": "{{ tag | slugify }}",
            "tag":  "{{ tag }}"
            }{% if not (loop.last) %},{% endif %}

{% endfor %}
        ],

        "tagsVenue": [
{% for tag in image.tagsVenue %}
            {
            "slug": "{{ tag | slugify }}",
            "tag":  "{{ tag }}"
            }{% if not (loop.last) %},{% endif %}

{% endfor %}
        ]

    }{% if not loop.last %},
{% endif %}

{% endfor %}
]
{% endcache %}

To randomize the order of images. Is that possible with .order and is that possible within cached template code? (As random would be "new" every instance.)

Note that I have the image crops and tag lookups inside the cached code, as those are intensive. The first answer, to shuffle the images after fetching them within the cached code, won't work, because the for loop on the image set is what needs to be cached.

What about composing a custom Twig array containing all the data you need. This does all your DB queries and because you write it in default sort order (randomize afterwards), you can cache all the heavy lifting of your template:

{# Cache an array of fake "ElementModels" #}
{% cache %}

{% set imagesArray = [] %}
{% set tagsColor = [] %}

{% for image in craft.assets %}

    {% for tag in image.tagsColor %}

        {% set tagColor = {
            slug: tag|slugify,
            tag: tag,
        } %}

        {% set tagsColor = tagsColor|merge(tagColor) %}

    {% endfor %}

    {% set imageObject = {
        url: image.url,
        title: image.title,
        tagsColor: tagsColor,
    } %}

    {% set imagesArray = imagesArray|merge(imageObject) %}

{% endfor %}

{% endcache %}

Then randomize your images and print the JSON:

{# Randomize our array #}
{% set imagesArray = shuffle(imagesArray) %}

{# Print the thing into our JSON #}
{% for image in imagesArray %}
    ...
{% endfor %}