Configure the "Entries" HTML Editor? I would like to configure the rich text editor in Entries->Singles content blocks like I do in my plugins and forms.  I know I can configure Redactor config within the /craft/config/redactor directory, but that does not impact the editor within //admin/entries/.

Where is the config for the admin entries editor?

If I'm understanding you correctly, you've got a Rich Text field you're using in one of your Single's field layouts.

That Rich Text field will have settings (under Settings->Fields->(click on the Rich Text field you're using for that single)).  From there, you can select the specific craft/config/redactor/config.json config file you'd like that specific Rich Text field to use.


Matrix Field Slug Output I am not sure why, but I cannot seem to get the short name/handle/slug of a matrix field that is a category field.  I need to get it's slug.

{% for row in entry.matrixField %}

 {{ row.matrixChild.slug }}

{% endfor %}

That is returning an ElementQuery. I'm assuming you only need to get the first category. You need to use .one to get the category element.

{% for row in entry.matrixField.all() %}
    {{ row.matrixChild.one.slug }}
{% endfor %}

If you wish to display more than one category you can use a {% nav %} or {% for %} to loop through them. See the category docs.


How to restrict access to some section in front-end for admin user only? I know this is a basic question, but i never use Craft this way.

I need to show a section ( list of items ) in the frontend but only available for admin users ( that are already logged in the control panel ).

How can achieve this restriction from the template?

Thanks!

One option is to do this:

{% if currentUser.admin ?? false %}

    ...this code can only be seen by admins...

{% endif %}

currentUser is a Global Variable on which you can pass the admin property. ?? is a null-coalescing operator which returns false if the currentUser (if there is one) is not an admin.

Edit:

So if you want to show this section to anyone logged in to the admin or client account in Craft Client, I'd recommend doing the following:

{% if currentUser ?? false %}

    ...this code can only be seen by admins...

{% endif %}

Basically, this says if the current user is logged in, display the contents. Since the only ones with logins are you and the client, this will only display the content to you!

If you'd like for the whole page to only display for certain users (for any unaccepted visitors it will throw a Craft 403 error page), you can add something like this to the top of your template:

{% requirePermission "permissionHandle" %}

(You can find a full list of permissions here.)

I'd recommend the accessCp permission handle if you're wanting to block everyone but the client and admin accounts for Craft Client.


Getting metadata/column names for empty resultset I have a dynamically generated sql. How can I know what the column names are, even if the database returns an empty result?

$sql = "select t.bar, count(o.foo) as amount
        from craft_table t join craft_otherTable o on t.id = o.id";
$resultset = craft()->db->createCommand($sql)->queryAll(true);

In Java, i can do something like this:

for(int i=0;i<resultset.getMetaData().getColumnCount();i++){
    columnNames.add(resultset.getMetaData().getColumnLabel(i))
}

I am looking for a similar solution in PHP.

I have tried this:

$command = craft()->db->createCommand($sql);
$command->prepare();
var_dump($command->getPdoStatement()->getColumnMeta(0));

...but the output is bool(false). I feel like I am missing something.

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

This is working for me

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

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


How to eager load user Images (photoUrl)? I've been trying to eager load user Photos, but it does not seem to work.

Here's my stripped down code:

{% set entries = craft.users({
    group: 'coWorkers',
    orderBy: 'lastName',
    with: [
        'getPhoto',
    ],

}) %}

{% for entry in entries %}
    {% set userImage = entry.getPhoto[0] ?? null %}
    {% if userImage|length %}

    {% endif %}
{% endfor %}

No photos are displayed.

Preferrably I would eager load with the transform as well:

{% set entries = craft.users({
    group: 'mitarbeiter',
    orderBy: 'lastName',
    with: [
        ['getPhoto', { withTransforms: ['user'] }],
    ],

}) %}

In Craft 2 I could eager load the following way:

{% set entries = craft.users({
    group: 'mitarbeiter',
    orderBy: 'lastName',
    with: [
        'getPhotoUrl(320)',
    ],

}) %}

Anyone has done this before?

Cheers
Stefan

Your source is set to :

{{ entry.getPhoto.getUrl('user') }}

When in order to access an image, you need to give the array index (as you have in your set statement):

{{ entry.getPhoto[0].getUrl('user')

or better yet, as you have already set it to a variable

{{ userImage.getUrl('user') }}

In full, while adding in to appropriate code for eager loading your transforms:

{% set entries = craft.users({
    group: 'coWorkers',
    orderBy: 'lastName',
    with: [
       [
           'getPhoto',
           { withTransforms: ['user'] }
       ],
    ]
}) %}

{% for entry in entries %}

    {% set userImage = entry.getPhoto[0] ?? null %}

    {% if userImage %}

    {% endif %}

{% endfor %}

If you need any further information, the Official Documentation does a excellent job of explaining how to implement this on the front end for craft 3


Persistent Form Data I am looking for some help with persistent form data.

If a user submits a front-end entry form for some Entries data, but there are errors with the submission, they are currently redirected to the entry page and successfully shown the errors (eg field is required). Is there a method or syntax where this form can also retrieve the posted form data so the user is not required to fill in the whole form again?

Many thanks for any help from the community!

Dan

If there are any problems with your submission, Craft sets an entry route variable1, which you can use to retrieve the previously-posted form data.

Here's an example of how you might do that:

<input
    id="title"
    type="text"
    name="title"
    value="{{ entry is defined ? entry.title : '' }}",
>

You can also retrieve the errors from the entry variable:

{% if (entry is defined) and (entry.hasErrors('title')) %}
    {{ entry.getError('title') }}
{% endif %}

If you want to learn more about the validation-related methods available on the entry object (such as the difference between getError and getErrors), I've written a blog post on the subject.

Stephen

Take a look at line 477 of craft/app/controllers/EntriesController.php


List months between a given date range I am trying to list the months (January, Febuary etc) between two dates.
I have a start date: 5/4/2015 and an end date: 9/25/2015.

Using range I am able to return the month numbers, but just can't figure out the correct syntax to convert 5 into May.

Here's what I've got so far, maybe there is a better way all together?

TWIG

{% set startMonth = craft.plugin.getStartDate() %} // returns 5/4/2015
{% set endMonth = craft.plugin.getEndData() %} // returns 9/25/2015

{% for month in range(startMonth, endMonth, 1) %}
    {{ month }}  // returns 5 6 7 8 9
{% endfor %}

I've tried doing something like: {{ month|date('F') }} but that returns December for each result.

I'll eventually need days within this month range, but I am hoping from this I can figure that out.

I made a Craft plugin that simply wraps PHP DatePeriod: "Date Period plugin for Craft". The plugin provides a datePeriod Twig function. It works really simple, your give it a start date, an end date and an interval to create a DatePeriod object.

datePeriod( startDate, endDate, interval )

This DatePeriod object you can now iterate over to get the dates, recurring at the set interval, over the period spanning your start and end date. By default the interval is set to 1 day, but you can modify that with the (optional) parameter.

{% set datePeriod = datePeriod(startDate, endDate, '1 month') %}

{% for month in datePeriod %}
    {{ month|date('F') }}
{% endfor %}

To also list the days in between, you would add Craft's group filter like so:

{% set datePeriod = datePeriod(startDate, endDate) %}

{% for month, daysInMonth in datePeriod|group('{ object|date("F") }') %}
    {{ month }}
    {% for day in daysInMonth %}
        {{ day|date('d') }}
    {% endfor %}
{% endfor %}


Performance when loading lots of Elements but only need limited data The performance of the ElementCriteriaModel for lookups is killing me.

I have 300 or so "People" entries in a craft site and trying to load them just for a basic listing page takes forever. There's just so much overhead.

In this case of i.e. a listing page, I need the entry title, slug and an image field (which I'm eager loading). I don't need all of the other fields and overhead it loads.

Is there a way to get more acceptable performance for cases like this specific one (listing page with large number of entries and limited data needed)? Or am I going to have to bypass the element criterea stuff and do the lookups myself in SQL?

Thanks

Not in Craft 2 without completely bypassing ElementCriteriaModel and building your own SQL query.

In Craft 3 (currently in beta) you can, though – you can override which columns get selected in your element queries, and you can choose whether you want the data returned as element models or just plain arrays.

{% set entries = craft.entries
    .section('news')
    .select('elements.id', 'content.title')
    .asArray()
    .all() %}


Unable to connect to db via console with a custom config directory path I've just used yiic for the first time for a plugin record installation and found that the db.php config file didn't seem to be picked up and I got database connection failures.

I added a console array to the file to try that but still no joy. So I edited the craft/app/etc/config/defaults/db.php with the username, password, table prefix and database name of my local install and it all works fine.

I've not tried this on a vanilla Craft install but I'm guessing that this may be because my config directory has been renamed to config-mydomainname as we are running 2 craft sites off of one craft instance.

That works by way of the following in the ./public_html/index.php file:

define('CRAFT_CONFIG_PATH', '../craft/config-mydomainname/');

Is this change of path causing the issue with the console?

I ran into something very similar to this today. I have a custom path for plugins, as a result I could no longer run the plugin console commands because yiic.php is looking in the default path as specified by its defines. You need to let yiic.php know about your custom paths and unfortunately I don't think this is possible at the moment without hacking it.


Feed Me relative paths I recently started a new Craft 3 project and am having some trouble with Feed Me. I haven't had this problem in the past with Craft 2.

The Feed URL I'm using is giving me this error:

Unable to reach assets/data/clients.xml. Message: cURL error 6: Could not resolve host: assets (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)

When I try to use the siteUrl it seems like that isn't resolving either:

Unable to reach {siteUrl}assets/data/clients.xml. Message: cURL error 6: Could not resolve host: %7BsiteUrl%7Dassets (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)

The file exists at that location and is accessible through the browser.

Any thoughts?

This is fixed in 3.0.0-beta.10. Additionally, there's no longer the concept of environment variables in Craft, instead we now have aliases. So instead of using:

{siteUrl}assets/data/clients.xml

Use:

@web/assets/data/clients.xml


Moving from staging (MAMP) to live production server I'm a long time WordPress developer who's moved over to Craft CMS (loving it).

When moving over WordPress sites from MAMP to a live production server, I follow this process:

Upload all WP files to live server
Export database via phpMyAdmin
Create database on live server and import database dump
User search and replace tool to change URLs
Flush permalinks via WP admin

For Craft, I've done the following:

Upload all Craft files to live server
Export database from CP in Craft
Create database on live server and import Craft DB zip
Via live Craft CP, change Site URL and Asset URL

Everything is working perfectly, but I just want to check I hadn't missed anything here? Not having to do a search and replace is awesome.

Everything looks good to go more or less, but #4 can be improved upon by creating a multi-environment config file.  This way, instead of having to change your site urls and base path (for assets) in the event you want to overwrite your local db with your live site db to sync it up, you just use a variable in the CMS like {siteUrl} or {basePath} that's set in your config file.

nystudio107 has a great article walking you through setting up a great multi-environment.

If you're feeling even more adventurous, I also highly suggest his Database & Asset Syncing article that allows you to run a command from your terminal to instantly pull down and import a copy of your database/assets from any environment you want into your local.


Ordering of products? What is the best method to organise products, and subsequently the order of these products within a group?

Currently I have setup a product type of Canine. I can access each of these products via a URL of /canine/productslug/ but I am unable to change the order of these products when viewed at /commerce/products/.

The shop will consist of two sections Canine and Equine. I don't think I need to have two product types as they contain the same structure/layout/format. So I can perhaps change the product type to general.

However, being new to Craft, I am unsure how I should be structuring these products? Presumably I need to create either categories or structures and then assign products to these?

I have done some searching but can't find anything to direct me over how I should be setting up the shop for product listings.

Can anyone offer some direction, advise or pointers for this?

Product types are really all about data concerns - so if the data you're storing for your canines/equines (hereafter known as dogs and horses to save some typing ;) ) - is the same, then you're right you don't need more than one product type.  So let's say you make one type of product Animal.

The most obvious tool for grouping that Craft provides is categories.  You might make a category group of Animal Categories, and then two categories in that Dogs and Horses.  You then add a categories field to your product type and select that category group as the source.

Then, when entering each product, you just choose the appropriate category at that time (i.e. you don't so much assign product to a category from the category itself, rather the product is related to the category using the field on the product entry).

In terms of then listing those on a listing (rather than individual) page, in the category settings, set your categories to resolve to e.g. animals/{slug} (i.e. an actual url might be animals/dogs and define a template for Craft to use.

When someone hits that url, your chosen template will be loaded, and this template will have an auto-populated variable of category you can then use that to filter your products display

{% set products = craft.commerce.product.relatedTo(category) %}
{% for product in products %}
    etc.

That's the basics of doing a listing

To sort orders, you can do it in any normal Craft way, such as by the title in alphabetic order:

{% set products = craft.commerce.product.relatedTo(category).order('title asc') %}

If you want an explicit order, you can do it at the template level by ids and used fixedOrder('true) and so on.  There is currently no GUI method of sorting products in Commerce.

(It is fair to say though that it would be nice to have a native ability to create a default sort order for products in the back end, by e.g. drag and drop, which does not exist currently.  You can achieve this by using a Commerce Products field (which is really a relations field, just to products) - and simply manually sort all your product in that, and use that field to build your listings, but this is kind of frustrating to be honest - as where you then store that field?  We use a global set for this currently but it's not ideal).


Craft 3: How to get Volume by handle? How can I get the details of an asset volume in Craft 3, if I only know the handle?

I found the Volumes and the Assets service, but I believe none of them provides a method for that purpose. The only thing I found was this:

Craft::$app->getVolumes()->getVolumeById($id)

But how do I get the id? I do not want to iterate over getAllVolumes()...

As of this commit, there is a Craft::$app->getVolumes()->getVolumeByHandle($handle) method you can call.


Getting started with Order Adjuster plugin Starting with the Business Logic plugin from https://github.com/lindseydiloreto/craft-businesslogic I'm following 3 for 2 etc with Craft Commerce to get started.

I have my main plugin file containing:

<?php
namespace Craft;
require_once('Adjusters/BusinessLogic_TaxRemover.php');

class BusinessLogicPlugin extends BasePlugin
{

    public function getName()
    {
        return 'BusinessLogic';
    }

    public function getDescription()
    {
        return '';
    }

    public function getVersion()
    {
        return '1.0.0';
    }

    public function getDeveloper()
    {
        return craft()->getSiteName();
    }

    public function getDeveloperUrl()
    {
        return '';
    }

    public function init()
    {
    }

    public function commerce_registerOrderAdjusters(){

        return [

            new Commerce_TaxAdjuster

        ];
    }

}

And within Adjusters/BusinessLogic_TaxRemover.php I have:

<?php

namespace Commerce\Adjusters;
use Craft\Commerce_LineItemModel;
use Craft\Commerce_OrderAdjustmentModel;
use Craft\Commerce_OrderModel;

class BusinessLogic_TaxRemover implements Commerce_AdjusterInterface {

    public function adjust(Commerce_OrderModel &$order, array $lineItems = []){

        $myAdjuster = new Commerce_OrderAdjustmentModel();

        $order->baseDiscount = $order->baseDiscount - 5;

        $myAdjuster->type = "Test";
        $myAdjuster->name = "Test Adjuster";
        $myAdjuster->description = "Takes $5 off the order";
        $myAdjuster->amount = -5.0;
        $myAdjuster->orderId = $order->id;

        //if your Adjuster affects lineItems rather than the total, you record the ids here
        $myAdjuster->optionsJson = ['lineItemsAffected'=>null];
        $myAdjuster->included = false;

        return [$myAdjuster];

    }

}

But whenever doing anything to the cart, I just get the error:

Error

Class 'Craft\BusinessLogic_TaxRemover' not found

C:\Users\clive\Desktop\repos\_craft\craft\plugins\businesslogic\BusinessLogicPlugin.php(38)

26     }
27
28     public function getDeveloperUrl()
29     {
30         return '';
31     }
32
33     public function init()
34     {
35     }
36     public function commerce_registerOrderAdjusters(){
37            return [
38             new BusinessLogic_TaxRemover
39
40            ];
41     }
42
43 }

To get an adjuster working, it's really all about consistent naming and making sure PHP can find the class.  Here are the main things to address:

Your adjuster should be defined in a file that matches it's classname

So in this case a folder off the main plugin folder:

 /craft/plugins/businesslogic/Adjusters/BusinessLogic_TaxRemover.php

Include the Adjuster class file.

You can do this (at least) two ways:

include or require the adjuster file in your main plugin class

e.g.

<?php
namespace Craft;

require_once('Adjusters/BusinessLogic_TaxRemover.php');

OR you can use Craft::import (which is probably the better way I guess?)

Craft::import('plugins.businesslogic.adjusters.BusinessLogic_TaxRemover');

** The Classname must match the filename **

So e.g. in this case

<?php

namespace Commerce\Adjusters;
use Craft\Commerce_LineItemModel;
use Craft\Commerce_OrderAdjustmentModel;
use Craft\Commerce_OrderModel;

class BusinessLogic_TaxRemover implements Commerce_AdjusterInterface {

   etc
}

You must also finally register your Adjuster with commerce

And again you must use the same classname (and be mindful of namespaces!)
So in this example:

public function commerce_registerOrderAdjusters(){
    return [
        new \Commerce\Adjusters\BusinessLogic_TaxRemover

    ];
}


Save Group Permissions I'm trying to programmatically set group permissions. I came across the method saveGroupPermissions(). According to the documentation all you have to do is pass in the group ID and then an array of the permissions you want to apply. Great, seems simple enough. So I attempted the following:

craft()->userPermissions->saveGroupPermissions($group->id, array("accesssitewhensystemisoff"));

The string accesssitewhensystemisoff is a built-in Craft permission, I'm not attempting to set my own custom permission... Not even sure if that's possible but we'll save that discussion for later.

Anyway this is not working and I have no idea why. There are literally zero examples of how to properly do this so I'm wondering if anyone else has solved this problem?

On a related note does anyone know if it's possible to set a group permission that gives access to a plugin? Or do I need to whip up my own plugin to handle that?

Thanks!

Try using accessSiteWhenSystemIsOff.  If you're on a case-sensitive file system, that will matter.

  does anyone know if it's possible to set a group permission that gives access to a plugin

You'll want a plugin for that. You can use the registerUserPermissions hook to register a custom permission.


Grouping by Date (Day) Not Working Correctly For a week-long schedule, I'm trying to group events that occur on the same day, and also fall into one of two classifications— they are free if a pass is purchased or not included in the pass.

{% set passEvents = craft.entries.section("event").eventForwardPass("No").find() %}
{% for date, entries in passEvents | group("eventStartDate|date('F d, Y')") %}

ONLY list Non-Forward Pass events.

{{date}}

      {% for entry in passEvents %}

{{ entry.title }}- {{entry.eventStartDate}}

      {% endfor %}

{% endfor %}

I'm only showing the date next to the title to verify when the code works properly. The problem I'm having is this code seems to return all entries that match the 'set' criteria under each date, rather than just the entries that match the 'set' criteria for that particular date.

I'm basing the code off of examples that would normally group by month or year. It seems like I'm asking for the right things, but obviously, the results tell me, that I'm asking for the wrong thing on the loop.

Figured it out. I actually asked for all entries for the group, rather than just the entries (events) that matched the date.

{% set passEvents = craft.entries.section("event").eventForwardPass("Yes").status('live','pending').order('eventStartDate').find() %}
{% for date, events in passEvents|group('eventStartDate') %}

{{date}}

    {% for entry in events %}

               {% if entry.eventLinkOverride == 1 %}

{{ entry.title }}

                {% else %}

{{ entry.title }}

                {% endif %}

        {% endfor %}
    {% endfor %}


Does Craft Commerce support multi-channel fulfillment and inventory? I have a client with several retail locations. They would like a single unified website for the chain, and many of the products will be the same at each location, but each location will need to handle its own orders, including fulfillment and inventory. Users should only have access to orders that pertain to their location (similar to how sections can be limited to certain users). Is there a native way to do this with Craft Commerce, or a plugin that would achieve the same thing?

The short answer is, out of the box, no it does not, currently.  Inventory handling is quite basic at the moment, for example.

You could probably deal with a lot of the access stuff via Craft users & permissions, but there's no doubt in my mind this would involve a very substantial amount of custom plugin development work, and I'm reasonable sure no such plugin currently exists.

Commerce is still a relatively young product, so who knows about the future, but right now it would not personally be my first choice for this sort of project.

(You could perhaps tackle them as separate installations and use things like the ElementAPI to push product content between the systems, though, if the key issue is content sharing as opposed to one unified back end).


Suspended users who have never logged in This may sound paradoxal but here it is.

Membership based site.

A new user starts as suspended.
An admin unsuspends.

The user uses the system.

If a membership expires, a user gets suspended again (in the cp).

I want (in the cp again, from a plugin) a list of of suspended users who have never logged in. New users basically...

craft.users.status('suspended').lastLoginDate(NULL)
craft.users.status('suspended').lastLoginDate('')

Neither of these work. Any light?

Doing this

craft.users.status('suspended')

Then this in the actual loop works

 {% if user.lastLoginDate is null %}

I just wonder why I can't just fetch it all in one go :)

This probably works: craft.users.status('suspended').lastLoginDate(':empty:')


Send email notification to user's email when their entry has been enabled Running craft 2 on a customer's site. They have users that sign up on the site to receive personalized quotes. What I'd like to do is send an email notification to that user after an admin has enabled the entry that the user created.
I can't find any plugins that do this specifically. I've been trying to customize sprout forms/email to do this, but I'm not having any luck.

You could build a small plugin to hook into Craft's onBeforeSaveEntry event (docs).
Before the entry is saved (and enabled), you'd check if it was previously disabled and its new status is live, if it is, send an email.
The code below should get you going.
Save it as NotifyPlugin.php in a craft/plugins/notify folder.
<?php
namespace Craft;

class NotifyPlugin extends BasePlugin
{
    function getName()
    {
        return Craft::t('Notify');
    }

    function getVersion()
    {
        return '1.0';
    }

    function getDeveloper()
    {
        return 'You';
    }

    function getDeveloperUrl()
    {
        return 'http://example.com';
    }

    function init()
    {
        // Trigger only from the Control Panel and Admin users
        if (craft()->request->isCpRequest() && craft()->userSession->isAdmin()) {

            // Catch the onBeforeSaveEntry event
            // https://craftcms.com/docs/2.x/plugins/events-reference.html#entries-onbeforesaveentry
            craft()->on('entries.onBeforeSaveEntry', function(Event $event) {

                // Isolate the entry from the event
                $entry = $event->params['entry'];

                // The ID of the section currently being saved
                $sectionId = $entry->sectionId;

                // The ID of the section you want to watch (change that to match your section ID)
                $sectionIdToWatch = 2;

                // Is this a new entry?
                $isNewEntry = $event->params['isNewEntry'];

                // Is it an entry from the section we are watching and NOT a new entry
                if ($sectionId == $sectionIdToWatch && !$isNewEntry) {

                    // Fetch the entry before save to use its status for comparison
                    // https://craftcms.com/docs/2.x/plugins/working-with-elements.html#fetching-elements
                    $currentEntry = craft()
                        ->elements
                        ->getCriteria(ElementType::Entry)
                        ->sectionId($sectionId)
                        ->status(null)
                        ->id($entry->id)
                        ->first();

                    // Entry status before saving
                    $currentEntryStatus = $currentEntry->status;

                    // New status being saved (from the event)
                    $statusBeingSaved = $entry->status;

                    // Are we going from disabled to live?
                    if(
                        $currentEntryStatus == BaseElementModel::DISABLED &&
                        $statusBeingSaved == EntryModel::LIVE
                    ) {
                        // Sets $toEmail to the entry's author but change to suit your needs
                        $toEmail = $entry->author->email;

                        // Prepare the message
                        $message = new EmailModel();

                        $message->subject = 'Your notification';
                        $message->body = 'Email content';
                        $message->htmlBody = 'Email content';
                        $message->toEmail = $toEmail;

                        // Send the message
                        craft()->email->sendEmail($message);
                    }
                }
            });
        }
    }
}

Change $sectionIdToWatch to match your section ID and as is, this will send the email to the entry's author.
As I said, this is just a base to get you going but it should work  :)


Changing the order of an 'archive' page I'm creating a monthly archive page (for a specified year) for a section.

Standard code to output the months and entries as follows:

{% set entriesInYear = craft.entries.section('blog').limit(null).after(year).before(year+1) %}

{% for month, entries in entriesInYear | group("postDate|date('F')") %}

{{ month }}

            {% for entry in entries %}

{{ entry.getLink() }}

            {% endfor %}

{% endfor %}

That's all working perfectly, what I can't figure out is how to reverse the order of the output, so I get January -> December, instead of December -> January.

I'm sure this is simpler than my head is making out, but that will teach me to be coding on a Sunday.

If you change your query and sort by ascending postdate, it will start with the oldest and end with the newest:

    {% set entriesInYear = craft.entries.section('blog').limit(null).after(year).before(year+1).order('postDate asc') %}


Entry URL Format - Parent + Children I created grouped category name projectCategory and assigned projects as the parent of design, 3d and art.

In project section (Channel) I have wrote {projectCategory.first().slug}/{slug}  and in categories (projectCategory) the top level is {slug} and nested categories {parent.uri}/{slug}.

Setup the field (projectCategory) so that I can assigned entry to selected category. So far

The result is not what I am hoping for at the moment sample.com/projects/mer-car-model is what generated. I was hoping that it should read sample.com/projects/3d/mer-car-model. I would appreciate some guidance how to achieve the result.

The above setting that I wrote is good until I forgot to change the limit number of selectable categories from 1 to 2 which solve my problem.  I think that was the problem for not showing the children due to limit to one select category. Now I can add two categories (The parent and child).


HTML/View Source button not working/showing in WYSIWYG Craft 2.5 / Redactor II 1.1.0 The "HTML" button no longer seems to show in the WYSIWYG. The button is set in the Redactor config file like so:

{
    "buttons": ["html","formatting","bold","italic","unorderedlist","orderedlist","link","image","video"],"plugins":["fullscreen","video"],
    "toolbarFixed": true
}

It turns out that the latest redactor seems to now have a plugin for viewing the source. You can enable this in your redactor JSON config file under plugins. Just add the "source" plugin like so:

{
    "buttons": ["format", "bold", "italic", "lists", "image"],
    "plugins":["fullscreen", "source"],
    "toolbarFixed": true
}


How can I determine which user triggered an update? Recently a user, using the admin panel, triggered a Craft CMS update. I would like to determine which user it was.  Is there any log of these actions where I can check for this?   If it's in craft/storage/runtime/logs/craft.log, can you please tell me what to search for?

That one is tricky.

I can't think of anything that gets logged in Craft's log files currently that would help determine that.

We do keep track of the request IP address in all of our web service logs, so if you wanted to send the domain along with the approximate update time to support@craftcms.com, we could at least send over the IP address the update was triggered from.  That won't help much if the person was sitting behind a proxy/DHCP server, though.


ElementAPI - Can I use javascript/ajax to load json Probably a dumb question, but since i wasn't sure while reading on github, i'll ask here.

I am wondering if I can reach the JSON I created with an URL or is it only for use in PHP?

I would like to load entries from craft from a json with ajax when i click on a button and i wasn't sure if it was possible with this plugin since there is no exemple.

Anybody can help me?

Thanks!

Totally do-able.

Once you have the ElementAPI plugin downloaded and installed, you'll want to make sure you have created a file called elementapi.php and it is in your /craft/config/ directory.

For simplicity's sake, I've used a stripped down version of the example on the github page.

elementapi.php

<?php
namespace Craft;

return [
    'endpoints' => [
        'news.json' => [
            'elementType' => 'Entry',
            'criteria' => ['section' => 'news'],
            'transformer' => function (EntryModel $entry) {
                return [
                    'title' => $entry->title,
                    'url' => $entry->url,
                    'jsonUrl' => UrlHelper::getUrl("news/{$entry->id}.json")
                ];
            },
        ]
    ]
];

Going back to your /craft/config/ directory, you will want to enable CSRF protection..

Finally, (again for simplicity) here is an example of getting my news entries via ajax on docReay

_layout.html

<head>
...
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js">  </script>
<script>
    $(function () {
        var data = {
            'CSRF': $('input[name="CSRF"]').val(),
        };

        $.ajax({
            'type': 'get',
            'contentType': 'application/x-www-form-urlencoded; charset=UTF-8',
            'cache': false,
            'data': data,
            'url': 'news.json',
            'dataType': 'json',
            'timeout': 50000
        }).done(function (response) {
            console.log(response);
        }).fail(function (error) {
                // Total fail.
            });
        });
    </script>
</head>

<body>
<div id="container">
    {{ getCsrfInput() }}
...

Then if you look at your console, you should see something like this:

{"data":[{"title":"We just installed Craft!","url":"http:\/\/craftsandbox.dev\/news\/2016\/we-just-installed-craft","jsonUrl":"http:\/\/craftsandbox.dev\/news\/3.json"}],"meta":{"pagination":{"total":1,"count":1,"per_page":100,"current_page":1,"total_pages":1,"links":[]}}}

Hope this helps!


How does the queue work? I'm trying to find documentation on how the queue system works, and what parts of craft relies on it. To my current understanding, the queue is normally executed when users are logged in to admin, and search indexes are updated via queue?
Also, I use webhooks, which seems to be executed the same way.
Publishing pending posts though, doesn't seem to use the queue?
I don't have any queue/listen task running, but since I'm running a dockerized version I could run a parallel container which just invokes craft queue/listen if needed, would that be favorable, and then I would disable the runQueueAutomatically setting I assume?
Since I'm also running this in AWS, I have the option to run the queue via SQS, what would be the benefits of that? I assume the default queue is just stored in the database, but I assume it is doing some sort of locking to prevent multiple executions, if I would have multiple queue daemons running. So only real benefit would then be, that the information isn't stored in database (thus, not part of backups for instance), because the load on the database seems abysmal for any normal scenario.

"How does X work?" is a very broad question, and not one I intend to try and answer in detail here. Below are a few resources that should help get you started:
Robust queue job handling in Craft CMS
How to best design large queue jobs?
Also, here are all questions tagged with queue:
https://craftcms.stackexchange.com/questions/tagged/queue
Hope that helps!!


Retrieving featured entry from a given category This piece of code used to work to retrieve 1 featured (lightswitch) entry per category.

{% for category in craft.categories %}
    {% set entries = craft.entries.find({
      section:    'news',
      limit:      '1',
      featured : '1',
      search :"category:" ~ category.title,
      order :'postDate desc'
    }) %}

Somehow I have to save a entry twice now before it appears. Any ideas whats wrong? Is this a craft bug?

There’s currently a bug with storing keywords based on related elements, which we’re looking into. Using the search parameter for this isn’t really the right way to go anyway, though.

Instead you should be using the relatedTo param:

{% set entries = craft.entries.find({
    section:   'news',
    limit:     1,
    featured:  1,
    relatedTo: { targetElement: category, field: 'category' },
    order:     'postDate desc'
}) %}

UPDATE

The aforementioned bug was fixed in Craft 2.1.2563.  You’re still better off using the relatedTo param though.

UPDATE 2

Fixed a typo in the above code block.


Using search criteria in modifyEntrySources plugin I have articles with a multi-select named theme.

This works fine in a template:

{% set entries = craft.entries.section('article').search('theme:themeFoobar') %}
<p>{{ entries | length }}</p>

I'm working on a plugin to create a custom source containing only those articles that have themeFoobar selected in their multi-select, this is what I have:

public function modifyEntrySources(&$sources, $context)
{
  $sources[] = array('heading' => 'Themes');

  $sources['theme:foobar'] = array(
    'label' => 'Theme: Foobar',
    'criteria' => array(
      'section' => 'article',
      'search' => 'theme:themeFoobar'
    )
  );
}

The result of this is that the source contains all articles, it looks like the search criteria is completely ignored.

Is search not the correct criteria to use here? Is there another criteria I can use to find only the articles with themeFoobar selected in the multi-select?

Further information

The multi-select used to be just a dropdown. When it was a dropdown, this plugin worked fine:

public function modifyEntrySources(&$sources, $context)
{
  $sources[] = array('heading' => 'Themes');

  $sources['theme:foobar'] = array(
    'label' => 'Theme: Foobar',
    'criteria' => array(
      'section' => 'article',
      'theme' => 'themeFoobar'
    )
  );
}

My solution, thanks to @carlcs:

public function modifyEntrySources(&$sources, $context)
{
    $sources[] = array('heading' => Craft::t('Themes'));

    $themes = array(
        'THEME_FOO' => 'themeFoo',
        'THEME_BAR' => 'themeBar'
    );

    $criteria = craft()->elements->getCriteria(ElementType::Entry);
    $criteria->section = 'article';
    $articles = $criteria->find();

    foreach ($themes as $theme => $label)
    {
        // Loop through all articles and check if they contain the current theme.
        // If they do, add it to the ids array which we will later use to filter
        // just the articles with this theme.
        $ids = [];
        foreach ($articles as $article)
        {
            foreach ($article->theme as $articleTheme)
            {
                if ($articleTheme == $themes[$theme])
                {
                    array_push($ids, $article->id);
                    break;
                }
            }
        }

        $sources['theme:' . $label] = array(
            'label' => Craft::t('Theme') . ': ' . Craft::t($theme),
            'criteria' => array(
                'section' => 'article',
                'id' => $ids
            )
        );
    }
}

The PHP itself could be cleaned up, but this works for now.

Categories would probably have been a simpler solution had I gone for that originally.


Transfer Dukt Analytics to new build I'm working on a new build of a site with a new database, I think that copying the plugin folder will not carry over the analytics statistics, are there database entries that I need to copy over?

Doesn't look like Dukt Analytics has any tables it creates in the database, but it does require Dukt OAuth, which creates a craft_oauth_providers table and a craft_oauth_tokens table you could move over.

Both of the plugin save their plugin settings in the craft_plugins table, so you might want to move their rows over as well.


Redirect all but certain requests to index I have a defined in routes.php a regex that redirects all queries but api to my index template:

return array(
   '<url:(?!api).*>' => ['template' => 'index']
);

I'm trying to exclude robots.txt as well as Google Analytics which is utm_source=analytics_test&utm_medium=referral I've tried the following but it's not quite right:

return array(
   '<url:^(?!api|robots|utm_source)(.*)$>' => ['template' => 'index']
);

This will redirect all queries but urls containing:
api or robots or utm_source strings

return array(
   '^(?!.*(api|robots|utm_source)).*$' => ['template' => 'index']
);


How to: Flexible Twig Templates in Craft I am just starting out with Craft CMS.

What I see right now is a lot of static content in the html templates. Even in the demo.

{% block content %}

{{ entry.title }}

{{ entry.body }}

Recent News

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

{{ entry.title }}

    {% endfor %}

{% endblock %}

You see, that is very static. Is there a way to make it all more flexible and dynamic?

I want my site to be totally flexible so that users can change the outcome completely with dragging and dropping sections in the admin area.

I only want to define HTML for a field / section. Then, I would simply need to loop all fields through and load the html template for each section that is being used.

This would allow massive reusability of these 'content boxes' everywhere. Basically, it'll become drag and drop website building to a large extend.

Do you have some advice on how to do this best?

Basically this guy is talking about it: https://mijingo.com/products/screencasts/reusable-twig-templates-craft/

I'm not sure I understand your question 100%, but I'm assuming you're talking about a thoroughly modular approach to templating, and not about letting your end users/content editors actually edit the content model (i.e. create/edit Sections, fields, field layouts etc) – because the latter is not a good approach, in general.

Either way, this is a very open question, so this answer is kind of broad (or in any case, it just outlines one way to do it, focused on entries and fields).

Note that I haven't seen the Mijingo videos, but I think the answer to your use case is probably to go with a partial-heavy approach. Basically, a "partial" is an incomplete/modular template that you can include in another template.

First off, you might want to create a "catch-all" template (let's just assume your catch-all template is called templates/index.html). Be sure to add the path to that template (which would just be index) to the Entry Template setting for all relevant Sections, to make sure the same, catch-all template is always loaded for all entry URLs.

Then, assuming your site has three fields – heading, image and body – you'd create a partial template for each of these fields. It's a good idea to store your partials in a folder prefixed with an underscore, to make sure Craft doesn't include them whenever it maps URL routes to template paths (these templates aren't standalone and should never be rendered on their own). So for the three fields in our example, you'd create these three templates:

/templates/_partials/heading.html
/templates/_partials/image.html
/templates/_partials/body.html

Here's how the heading.html partial could look:

{% if element.heading %}

{{ element.heading }}

{% endif %}

Inside your catch-all template, you'd then need to {% include %} these partial templates, following some logic of your choice.

Here's an approach that basically loops through all fields for the current entry's field layout, attempting to include a partial template for each field:

{% extends '_layout' %}{# Assuming this template extends a basic layout template #}
{% block content %}

    {# Get all fields, indexed by field ID #}
    {% set allFields = craft.fields.getAllFields('id') %}

    {# Get the IDs for all fields in this entry's field layout #}
    {% set fieldIds = entry.getFieldLayout().getFieldIds() %}

    {# Loop through the entry fields' IDs; attempt to include template based on each field's handle #}
    {% for fieldId in fieldIds %}
        {% set field = allFields[fieldId] ?? null %}
        {% if field and entry[field.handle] %}
            {% include '_partials/'~field.handle ignore missing with { element: entry } %}
        {% endif %}
    {% endfor %}

{% endblock %}

A couple of things to note:

First, the above code builds the template path to each partial dynamically, by joining the root path ('_partials/') with each field's handle property (using the tilde operator ~). In other words, this solution hinges upon using the fields' handles for the partial templates' filenames. Note that its also possible to pass an array of template paths to the {% include %} tag, in which case Craft will attempt to load the next template in that array whenever it fails the load the former. Here's how that could look:

{% include ['_partials/matrix/'~field.handle, '_partials/fields/'~field.handle] ignore missing with { element: entry } %}`

With the above, Craft would first look for the template /templates/_partials/matrix/title.html, and if that file doesn't exist it'd look for /templates/_partials/fields/title.html (before failing silently due to the ignore missing directive).

Second, it might seem redundant to pull all fields from the FieldsService, but the alternative is to hit the database for every field in your entry's field layout, so this should actually be the most performant way to pull the current entry's actual FieldModels.

Third – the with statement for the {% include %} tag enables you to pass parameters to the included template. In this example, we're actually exposing the current entry to the included template as the more generic element variable. This is just future proofing in case we want to use the same partials for other element types, e.g. categories (in which case you'd use with { element: category }) – notice that in the example heading.html template above, element.heading is used over entry.heading.

If you want to avoid variable pollution, you might pass the only directive aswell, in which case only whatever parameters passed with with will be made available to the included statement, nothing else:

{% include '_partials/'~field.handle with { element: entry } only %}

Of course, you can include other stuff in the object passed to with, as well. For instance, you might want to render stuff differently if the current field is either first or last in the loop:

{% include '_partials/'~field.handle with { element: entry, isFirst: loop.first, isLast: loop.last } %}

{# In heading.html #}

{{ element.heading }}

Going further; talking about Matrix fields and alluding to the fact that putting Matrix field partials in a separate templates folder might be a good idea – if you're going fully modular it might make sense to create separate templates for each Matrix block type, as well. Tons of ways to skin this cat, but one way to do it is to add a sub folder for every Matrix field, containing partials for each of the field's block types. For example, if you've got a Matrix field called contentBlocks with the block types images and text you might structure it like this:

templates/_partials/contentBlocks.html (the partial for the Matrix field itself)
templates/_partials/contentBlocks/images.html (the partial for the images block type)
templates/_partials/contentBlocks/text.html (the partial for the text block type)

Then, inside the contentBlocks.html template, you could do something like this:

{% for block in element.contentBlocks %}
    {% include '_partials/contentBlocks/'~block.type ignore missing with { block: block } only %}
{% endfor %}

In fact, you might not even need the contentBlocks.html field template, and just do something like this in index.html:

{% if field.type == 'Matrix' %}
    {# Attempt to include the blocks for this Matrix field #}
    {% for block in entry.field %}
        {% include '_partials/'~field.handle~'/'~block.type ignore missing with { block: block } only %}
    {% endfor %}
{% else %}
    {# Non-Matrix fields #}
    {% include '_partials/'~field.handle ignore missing with { element: entry } %}
{% endif %}

One final thing to note – with the above solution, your entries' fields' partials will be included in the order corresponding to the entry type's field layout (i.e. the first field in the layout will be included first). This may or may not be what you want (the order that makes sense inside the CP may not always correspond to what the design/front end should look like) but if you need more control over your fields' order, you could do something like this inside index.html:

{% set fieldsToInclude = ['image', 'heading', 'body'] %}
{% for fieldHandle in fieldsToInclude %}
    {% if entry['fieldHandle'] %}
        {% include '_partials/'~fieldHandle ignore missing with { element: entry ) %}
    {% endif %}
{% endfor %}

The above will actually be slightly more performant than the first example, because it avoids the few database queries involved in pulling the fields dynamically.

Of course, for optimal flexibility you'd probably go heavy on the Matrix fields, too – obviously, any Matrix block partials would render in their original order inside the Matrix fields, so with Matrix blocks your content editors will have complete control over where each piece of content actually renders.


Internal Server Error: SQLSTATE[42000] 1118 Row size too large I have a very large entry type in craft with quite a few fields.  I've been updating a single record on a regular basis but upon adding a few more paragraphs of rich text in a field, I received this error when trying to save:

  Internal Server Error

  CDbCommand failed to execute the SQL statement: SQLSTATE[42000]: Syntax error or access violation: 1118 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.

Is there some other solution beyond what the error is suggesting? Not sure what I'm missing. Any thoughts would be appreciated.

Thanks!

UPDATE 10/1

I was able to get the existing table in my Craft instance updated to the barracuda file format with row_format=DYNAMIC. Updated the global MySQL params as well:

+--------------------------+-----------+
| Variable_name            | Value     |
+--------------------------+-----------+
| innodb_file_format       | Barracuda |
| innodb_file_format_check | ON        |
| innodb_file_format_max   | Barracuda |
| innodb_file_per_table    | ON        |
+--------------------------+-----------+

The problem now is with new matrix fields: the newly created tables are not being set to the row_format=DYNAMIC. Is there somewhere in Craft where I need to update this? Or is there somewhere else I need to update this?

You're running into a MySQL/InnoDB server limitation that commonly occurs with a significant number of columns in a single table.

Fortunately, there are several documented workarounds for it:

https://stackoverflow.com/questions/15585602/change-limit-for-mysql-row-size-too-large

https://www.percona.com/blog/2011/04/07/innodb-row-size-limitation/

https://dba.stackexchange.com/questions/6598/innodb-create-table-error-row-size-too-large

From the Craft side, another workaround would be to re-think your information architecture. Currently, most fields in Craft have their content stored in the craft_content table in the database, so when you have a lot of textual fields on the site, you'll see the error you're getting.  The exception to this rule is Matrix fields, which get their own table where their content is stored.

If you can move any of those fields into Matrix fields where they make sense, you'll take them out of the craft_content table helping mitigate the issue.


Commerce 1 find if Discount object is valid based on start/end dates (Twig) In Twig, I want to find out if a discount is valid based on start/end date.  startDate and endDate don't seem to exist and I can't inspect the discount object by using the json_encode filter (returns {}).

How can we do this?

This is the code used to grab the discount object:

{% set discount = null %}
{% for d in craft.commerce.discounts %}
    {% if d.id == 1 %}{% set discount = d %}{% endif %}
{% endfor %}

name, description and enabled variables are available but no startDate/endDate.

In Commerce 1, craft.commerce.discounts will return an array of Commerce_DiscountModel objects of all available discounts.

public function getAllDiscounts($criteria = [])
{
    $records = Commerce_DiscountRecord::model()->findAll($criteria);

    return Commerce_DiscountModel::populateModels($records);
}

Commerce_DiscountModel objects have a dateFrom and a dateTo property, which is probably what you're looking for.

Completely untested, but something like this:

{% set discount = null %}
{% for d in craft.commerce.discounts %}
    {% if d.id == 1 %}
        {% set discount = d %}
        {% if discount.dateTo > '2018-01-01 00:00:00' and discount.dateFrom < '2018-12-31 23:59:59' %}
            Matches!
        {% endif %}
    {% endif %}
{% endfor %}


Two plugins contain the same function name so they're conflicting I'm trying to use a filter function from a plugin, but it turns out two plugins that I have installed have the same function name and the wrong one is getting called. For now I edited the vendor files to rename the function, but I don't want that to be my final solution in case I want to upgrade the plugin later.

What is the best way to go about circumventing this type of conflict between two plugins?

You could get around this by creating your own renamed copies of those functions.

Create a module.
Copy the content of each affected plugin's twigextensions folder to your module's twigextensions folder.
Adjust the namespaces in these files to match your module
Rename the functions / filters in these files to something unique.
Load these twigextensions in your module's main file (use statement plus Craft::$app->view->registerTwigExtension).
You can now use the filters in twig by referencing the unique name you gave them.

If you haven't worked with modules before, you can use pluginfactory.io to scaffold a module that includes lots of example code, including all the required code to set up a twig extension.

To improve on this further, instead of a straight up copying of the twig extensions, refactor them to call the public functions in the original plugin files. This will ensure it's much less likely to break things when the plugin gets updated later.


Having trouble with Bilingual URLs I'm in the midst of setting up a bilingual website. English and Welsh.

I have set up the locales in my settings (en and cy_gb)

My directories have the necessary folders for each language, with each containing their respective index.php and htaccess files.

Craft's general config file is changed. Basically I have followed the steps in the Craft docs. My site loads and clicking links loads them fine, but when I add a cy to the URL, I get a Craft 404 page

Is there anything I maybe missing? Do I need to add something to the templates themselves? Any help would be appreciated.

General config

return array(
// Base site URL
'siteUrl' => array(
    'en' => 'https://site.domain.net/',
    'cy_gb' => 'https://site.domain.net/cy/'

),

/cy_gb/index.php

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

//Tell Craft to serve the Welsh content
define('CRAFT_LOCALE', 'cy_gb');

/en/index.php

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

//Tell Craft to serve the English content
define('CRAFT_LOCALE', 'en');

Looking at the code you posted looks like you should change /cy_gb/index.php to /cy/index.php. /cy/ is the actual subfolder you are requesting here: https://site.domain.net/cy/


Using a Sprout Form within a Sprout Form? I'm creating a website where members have a form of questions to fill in each day. But within this form is a another set of questions that are always the same each day, but will have different answers in each day (it's like a diary entry, but built up of various fields).

Is there a way in Sprout Forms for a form to be almost "embedded" in others? So that if the fields in the embedded form are changed they then change across all the parent forms it is included in, if that makes sense?

The only way I can think to do it at present is create a form with 2 tabs: main and diary. The main tab will contain specific fields for that day, the diary tab will have the set questions that are asked each day. And then I do a "save as" to duplicate the diary fields into another form and change those in the main tab. Issue is that if the diary structure ever gets changed / updated I would have to manually do this perhaps 30 or so times.

There is no default way to add a form within a form in Sprout Forms. Your proposed manual solution seems like a decent approach, but whenever you change a question on an existing form you will also be altering the historic data in any of your reports.

A two-forms approach

A more straightforward approach may be to make your process two forms. Have a primary form that has the core questions that don't change and a second form that the users are directed to for the questions that do. You could use a Form Relations as a Global Field or on a particular Single to assign which secondary form was needed and should be able to link between the submitted entries by tracking the IDs via a Sprout Fields Hidden Field or developing a custom front-end field that created the relationship in a more user-friendly way.

Using two forms will help you maintain accurate historic data and stick within existing functionality which will likely be easier to maintain in the long run.

A custom field approach

More speculatively, you could potentially develop a custom plugin and custom field that help you do this. It would definitely require a bit of planning, and I probably would vote against going this route, but to highlight some of the challenges you would face, here are some initial thoughts on what that might look like:

The fields that change would probably need to store data in a similar way. If all the fields that needed to change were Plain Text fields, that will likely be much easier of a problem to try to solve than if you need to swap questions that relate to different types of fields. It will likely be easier if the number of questions also stayed the same.
Sprout Forms stores fields locally to each form created, so you would not be able to use the Field Settings to control global attributes, you would need a separate custom field plugin settings area where you could control settings, such as the labels of the questions that change, across all instances of where the fields are used.
You'd probably also run into some challenges on how to create reports on the historic data. If answers to the questions of the first month relate to different questions than the answers to the data of the second month, you'd also have to find a way to store the questions that were being answered as part of the form submissions to know what the responses were actually referring to.


Cannot login to admin portal When I try to login to the Craft admin portal, I receive a prompt that my login credentials are incorrect, even though I am sure I have them set to the correct value.

Of note, this site is using a subdomain similar to craft.domain.com

I receive a prompt that my login credentials are incorrect, even though I am sure I have them set to the correct value.

If you're sure they're correct, then maybe Craft is connecting to a different database/Craft installation on the server than the one you think it's connecting to?

If you have access to the database, you can check to see if your user exists in the craft_users table and you can manually force a password reset like so: https://craftcms.stackexchange.com/a/13966/57


Dynamic Subfolders leaving empty folders behind I have {status}/{category}/{slug} as the path for uploading photos. When the status changes on the entry, then the photos associated with that entry move to the correct folder.

However, it leaves behind empty {category}/{slug} folders in the {status} folder it used to sit in. I don't believe it did so when I tried {status}/{slug} -- is it possible to do this without leaving debris in the previous folders?

When Assets moves files around because of dynamic Assets folder changes, it does not remove empty folders.

On the surface it seems like a no-brainer - just check if the folder is empty and if so, then nuke it! But if you go deeper, it gets complicated.

Should the physical folder be removed as well? If not, then the next time you index Assets, the folder will be reinstated. If yes, then what to do if there are unindexed files in there? Remove anyway? That's destructive. Don't remove? Then that makes Craft behave differently based on something that is out of its scope. What would users want in this case? Who knows!

You see, it's a bit tricky especially in terms of what the users would expect out of that functionality, so we just instead decided to go with leaving empty folder, as the folder path changing should not be that often of an occurrence and does not set us up for complex support tickets down the road.


\ns\prefix\Plugin::getInstance() returns null from another plugin in Craft 3 I'm building a plugin that extends the functionality of the Contact Form Tuner plugin and customize the email recipients based on different scenarios.  The email addresses need to be managed in the plugin settings using forms.
 Thus, I need to grab the settings from my plugin to be used in the Contact Form Tuner config file.

The problem I'm having is that I can't access my plugin from the Contact Form Tuner config file.  The getInstance method returns null.  I know I have the namespace and class name right because the same statement works when running it from my plugin class.

I also noticed that Contact Form Tuner seems to be loading before my plugin when testing with die statements in both plugins.  Is this the reason?

Is there any way around this?

Any help is appreciated.  Thanks!

I also noticed that Contact Form Tuner seems to be loading before my plugin when testing with die statements in both plugins. Is this the reason?

This.

You're probably doing this from your plugin's init() function.  If you listen to the EVENT_AFTER_LOAD_PLUGINS event and do your logic there, it should work.


Include Global Set Variable in Print Delimiters I have a site which has another group site - both use same templates but I want to include different phone number in the header of each.

I was wanting to use Global Set Variables to pull this information in.

It works fine in the execute delimiters but not in the print delimeters.

This works fine:

{% include "includes/#{ craft.config.siteCode }/head-constants" %}

Is there any way to include it within another variable like below:

{{ #{ craft.config.siteCode }Defaults.defaultTelephoneLink }}

This gives the Template Error: Unexpected character "#".

You'd want to do something like this:

{{ "#" ~ craft.config.siteCode ~"Defaults.defaultTelephoneLink" }}


Getting Matrix field ID and Block ID for my Custom Field I have a custom field that will be saving data to its own table. So if my field is in a Matrix field, I need to save the Matrix Field ID and Matrix Block ID to my table so I know what the data belongs to. I’m having a hard time figuring out how to get that data in my fieldtype. I’m using the onAfterElementSave method. I’ve been looking for attributes and types and whatnot on $this, $this->element->getType(), $this->element->getType()->getAttributes() and so far I’m just not having any luck finding this information. Can anyone point me in the right direction here?

The BaseFieldType class (which all FieldTypes extend) has a contentPostLocation property, which will give you the "path" to the field inside the entry model. The value is returned as a string, e.g. fields.myCustomFieldTypeHandle.

If your field is inside a Matrix block, the contentPostLocation path will include the Matrix field's handle – as well as the block ID – e.g.

fields.matrixFieldHandle.12.fields.myCustomFieldTypeHandle

Based on this, by exploding the contentPostLocation string and testing its length, you can figure out if the field is "standalone" or embedded in a Matrix block:

$contentPath = explode('.', $this->contentPostLocation);
if (count($contentPath) > 2) {
    // Not standalone (i.e. probably inside a Matrix block)
}

The Matrix' field's handle will be the second segment in the path. You can use the FieldsService to pull the actual field, in order to get its ID. It's probably also a good idea to confirm that it is indeed a Matrix field, which is easily done by checking its fieldtype's classHandle property:

$matrixFieldHandle = $path[1];
$matrixField = craft()->fields->getFieldByHandle($matrixFieldHandle);
if ($matrixField && $matrixField->fieldType->classHandle === 'Matrix')
{
    // Yup, it's a Matrix field!
    $matrixFieldId = $matrixField->id;
}

Finally, the block ID would be the next segment in the contentPostLocation path, i.e. $matrixBlockId = (int) $contentPath[2];

Putting it all together, something like this should do the trick:

public function onAfterElementSave()
{
    $contentPath = explode('.', $this->contentPostLocation);
    if (count($contentPath) > 2)
    {
        $matrixFieldHandle = $contentPath[1];
        $matrixField = craft()->fields->getFieldByHandle($matrixFieldHandle);
        if ($matrixField && $matrixField->fieldType->classHandle === 'Matrix')
        {
            $matrixFieldId = $matrixField->id;
            $matrixBlockId = (int) $contentPath[2];
        }
    }
}


Intalling Craft in the webroot folder I know this is bad practice but it's just for dev sites and there's no easy way around it with our current hosting provider. Anyway, I have my craft folder next to my index.php and $craftpath set to:

$craftPath = './craft';

Still I get this error:

Could not find your craft/ folder. Please ensure that $craftPath is set correctly in /chroot/home/rizencre/rizenweb.com/html/terravant/index.php

I just tested it for you and this

$craftPath = './craft';

or this

$craftPath = 'craft';

does both work for me!

This probably doesn't help you much; I only wanted to confirm, that your $craftPath = './craft'; config should be working for your file structure.


Default Craft entry limit There seems to be a default limit to for loops in craft of 100.

I have a channel with quite a few entries.

How can I disable this without writing nasty things like .limit(100000000)


How do I make my variable available inside an assets loop? I have an entries field called 'customerLogoBarUrl'. It contains one entry. So I can do this:

{% for item in entry.customerLogoBarUrl.limit(1) %}
  {% set theUrl = item.url %}
{% endfor %}

But then I need to output that variable inside an assets loop:

{% for item in entry.customerLogoBar %}
  {% for asset in item.logo %}

  {% endfor %}
{% endfor %}

This yields theUrl doesn't exist.

Your problem is a scoping issue. You've defined theUrl inside the scope of a for loop, so it only ever lives inside of that loop.

You can do this to have it exist outside of the loop, too.

{% set theUrl = '' %}

{% for item in entry.customerLogoBarUrl.limit(1) %}
    {% set theUrl = item.url %}
{% endfor %}

{% for item in entry.customerLogoBar %}
    {% for asset in item.logo %}

    {% endfor %}
{% endfor %}


Problem Saving Enupal Plugin Settings Description

I’m having an issue getting Enupal Snapshot working on our staging server. The settings do not want to save in the craft admin.

It isn’t obvious what the error is. I have checked my log files and this is the only error I see replating to Enupal's plugin. I think this is a red herring as I have this working on my local environment.

2019-11-13 09:16:37 [-][1][-][error][enupal\snapshot\Snapshot::error] Something went wrong when creating the PDF file: Error executing "ListObjects" on "https://franklin.ams3.cdn.digitaloceanspaces.com/?prefix=tools%2Finnovation-assessment%2F&delimiter=%2F&encoding-type=url"; AWS HTTP error: Client error: `GET https://franklin.ams3.cdn.digitaloceanspaces.com/?prefix=tools%2Finnovation-assessment%2F&delimiter=%2F&encoding-type=url` resulted in a `403 Forbidden` response:

Steps to reproduce

run which wkhtmltopdf outputs /usr/local/bin/wkhtmltopdf
Save path to plugin settings

Additional info
Craft version: 3.3.9
PHP version: 7.2.24
Database driver & version: MySQL 5.7.27
Plugin version: 1.2.6

Error executing "ListObjects" on "https://franklin.ams3.cdn.digitaloceanspaces.com/?prefix=tools%2Finnovation-assessment%2F&delimiter=%2F&encoding-type=url"; AWS HTTP error: Client error: GET https://franklin.ams3.cdn.digitaloceanspaces.com/?prefix=tools%2Finnovation-assessment%2F&delimiter=%2F&encoding-type=url resulted in a 403 Forbidden response:

That's an AWS error, so I'm guessing you're trying to save the output to an S3 bucket, but the credentials you've configured the S3 buck with does not have "ListObjects" permissions on the bucket.


In Craft Commerce, is it possible to make the product variant weight a required field? In Craft Commerce, is it possible to make the product variant weight a required field?
We are using weight to calculate shipping so it would be good if we could make it a required field to ensure that the store admin doesn't forget to enter it.
Thanks

Yes you can, using the Model::EVENT_DEFINE_RULES Put this in your customer module or plugin.
        use craft\commerce\elements\Variant;
        use craft\base\Model;
       use craft\events\DefineRulesEvent;

        Event::on(
            Variant::class,
            Model::EVENT_DEFINE_RULES,
            function(DefineRulesEvent $event) {
                $rules = $event->rules;
                $rules[] = [['weight'], 'required'];
                $event->rules = $rules;
            }
        );


Use Same Email Address On Multiple User Accounts I am needing to set up two distinct users (one for each of two LDAP log ins) and I need for them both to use the same admin email address.  However, Craft 2 will not let me do this.  Is there a way to do this for this type of special admin/ldap user?

Thanks

Not natively because Craft places a unique index on the email column of the craft_users table in the database.

Without knowing the specifics of what you're trying to achieve, I'd probably write a custom plugin that listened to user registration events in Craft and saved the necessary LDAP information in its own database tables that had foreign keys back to the native craft_users table.


How do I get the right entry data based on locale and slug? My site has 2 locales: en_us and nl_nl. I also have a Structure section called Pages, which targets both locales. For each locale, the section has an Entry URL Format:

en_us: en/{slug}
nl_nl: nl/{slug}

The Entry Template setting for the section is pages/_entry, and there is a template there.

Now, for an entry with the slug home for both locales, the URI nl/home gives me the correct page, but en/home gives me a 404.

Is my setup wrong? Do I need to explicitly create nl and en template folders?

Probably the CRAFT_LOCALE isn't set correctly. There is an in-depth knowledge article here.

To solve this, you could add a conditional to the /public/index.php:

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

//Locale
if ( preg_match("/\/nl\//i", $_SERVER['REQUEST_URI']) ) { //Check if /nl/ is in the uri
    define('CRAFT_LOCALE', 'nl_nl');
}
else {
    define('CRAFT_LOCALE', 'en_us');
}


Filter entries by ajax to controller Short story: I need your help sending value from dropdown selection as data to controller so my div updates with the filtered entries based on the selection.

Long story and code: I have a listing of entries in my template as follows:

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

{{ entry.title }}

{% endfor %}

I know I can filter those results with a field handle by updating the first line above with:

{% for entry in craft.entries.section('live').hostSite('weDo').find() %}

However I'd like to filter that listing of entries with a dropdown list that contains the available field handles, ie 'weDo, 'theyDo':

<select class="filter">
    <option value="all">all sites</option>
    <option value="weDo">sites we host</option>
    <option value="theyDo">sites they host</option>
</select>

I'd like to do this with Ajax and a controller I set up:

**Javascript**
// Add an event listener for filter clicks
$(function () {
    $('body').on('change', 'select.filter', onFilterClick);
});

// Event handler for the filter click
function onFilterClick (e)
{
    e.preventDefault();
    var data = this.value;

    $.ajax({
        method: 'get',
        url: 'actions/websiteListing/checkStatus',
        data: data,
        headers: {'Content-Type': 'application/x-www-form-urlencoded'}
    })
    .success(function(data) {
        $('.livelisting').html(data);
    })
    .error(function(data) {
        console.log('error', data);
    });
}
**Controller**
<?php
namespace Craft;

class WebsiteListingController extends BaseController
{
    protected $allowAnonymous = true;

    public function actionCheckStatus()
    {
        $criteria = craft()->elements->getCriteria(ElementType::Entry);
        $criteria->section('live');
        $criteria->hostSite = 'weDo';
        $criteria->limit = null;

        $entries = $criteria->find();

        foreach ($criteria as $entry) {
            echo $entry->title . '
';
        }
    }
}

I know the ajax is pretty trashy, but the url to the controller file is working correctly because when I make a selection from the dropdown menu, my div.livelisting is replaced by the single entry available with the field handle of 'weDo'.

Here's where your help is needed! The 'weDo' value in my controller needs the data sent from Ajax. Thanks for your expertise.

I did a little more research on Ajax and found a solution. I updated my Ajax such that the data line looks like:

$.ajax({
    method: 'get',
    url: 'actions/websiteListing/checkStatus',
    data: {filter: data},
    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})

Then in my controller, I was able to pass that data by adding $filter to the first line and including that for my 3rd $criteria line:

public function actionCheckStatus($filter)
{
    $criteria = craft()->elements->getCriteria(ElementType::Entry);
    $criteria->section = ('live');
    $criteria->hostSite = $filter;
    $criteria->limit = null;

    $entries = $criteria->find();

    foreach ($criteria as $entry) {
        echo $entry->title . '<br>';
    }
    die();
}


Nice-looking URLs for assets Is there a way to get "vanity URLs" for my assets? Something like:

www.example.com/download/asset.pdf

rather than:

www.example.com/several/subfolders/for/organisation/purposes/asset.pdf

I know that dumping all assets into a /download folder will work but this is far from an ideal solution. Is there another way?

Perhaps using redirects and Regex in your .htaccess? There's a Craft plugin that would help with this.
https://github.com/rkingon/Craft-Plugin--Redirect-Manager/

You could use something like:

RedirectMatch 301 /download/(.*) /several/subfolders/for/organisation/purposes/$1

You would need to refine this for matching several different subfolders.


Craft Commerce: No Emails sent on Default Order Status I noticed while doing some testing that assigned emails for the default order status do not get sent. An email does get sent on every other order status change without any problems. Has anyone else had this issue?

I just tested this with a default Craft Commerce installation, assigned an email to the default "Processing" order status, placed an order and received the email as expected.

I'd double check under Settings->Email in the Craft control panel you're not using phpmail or sendmail and you're using a proper SMTP server or transactional email provider like Mailgun or Mandrill, etc.  The others are notoriously unreliable at delivering email.  See: https://craftcms.com/support/troubleshooting-email-errors#dealing-with-email-delivery-issues


Loop through matrix field find first block of a type I'm trying to loop through a matrix field that has a few different types of fields in it and different orders. I want to first the first field of a certain type and output only that. Here is what I have so far.

{% for block in entry.blogPostMainSection.all() %}

{% if block.type == "blogText" %}

    {% set articleText =  block.blogArticleText %}

        {% if articleText | length > 100 %}

            {% set articleTextTrim = block.blogArticleText|slice(0, 100) ~ '...' %}

            {{articleTextTrim | striptags}}

        {% else %}

            {{articleText | striptags}}

        {% endif %}

{% endif %}

{% endfor %}

{% set myFirstMatrixBlockWithType = entry.blogPostMainSection.type('blogText').one() %}

{{ myFirstMatrixBlockWithType.articleText }}

Keep in mind entry.blogPostMainSection is not an array of blocks but a Query


Can entries be disabled by default for 2/3 of the languages on my website I have a 3 language website that I made for a client.
The website is in Dutch, Japanese and English.

When my clients creates a new entry, most of the time they want to have the Japanese and English version disabled and only show the Dutch version. After they have created the entry they have to manually disable the Japanese and English version.

Is it possible to have the Japanese and English version disabled by default?

Thanks!

Is it possible to have the Japanese and English version disabled by default?

Yes. Visit Settings -> Sections -> [Your Section Name] inside the Control Panel.

Under the heading Which locales should entries in this section target? there's a Default Entry Status Lightswitch for each locale. Make sure the Lightswitches are off (i.e., not green) for the English and Japanese locales, and you're all set.

Obviously, you'll need to do this for any and all sections targeting the 3 locales – there's no "global" setting for it.


Looping through images in a Asset field type Sorry, this is kind of a newbie question, but I can't figure out how to loop trough all images in one image asset field supporting multiple images.

The only way I have been able to output anything without an error, is this:

{% set asset = entry.wireframeImages.first() %}

{% if asset %}
    {{ asset.url }}
{% endif %}

But as you can see, only the first image is printed out.

How can I loop trough all images from this field?

I have been reading trough this page, but can't figure out how to do this simple task.

Thanks

An Asset field – like all relational fields, including Entries, Categories etc – always return an array-like object which is an instance of a class called ElementCriteriaModel. To output the actual file data, this means you have to loop on the field, e.g.:

{% for asset in entry.wireframeImages %}

{% endfor %}

The above is true even if there's 1 Asset selected in the field, or 100.

The cool thing about the for loop in Twig is that it won't throw an error if you attempt to loop on an empty array or object. This means that you don't have to wrap the loop in an {% if %} statement to take care of cases where the Asset field may be empty. Moreover, you can add an {% else %} statement to the for loop, which will be executed if the field is in fact empty:

{% for asset in entry.wireframeImages %}

{% else %}

Nope, no images here :(

{% endfor %}

In situations where your Asset field is limited to 1 file, a loop may seem like overkill – then you can use

{% set asset = entry.wireframeImages.first %}

to get the first (and only) file. Keep in mind though, that if the Asset field is empty, calling first on it will in fact produce an error. To get around this, you can use the default filter to add a default value to the variable and suppress the error. In these cases you have to have a conditional testing the value as well, though – so the amount of code is about the same as just using a for loop:

{% set asset = entry.wireframeImages.first|default(false) %}
{% if asset %}

{% endif %}

Note that first isn't the only method available to ElementCriteriaModel instances, check out the official docs to read more about it.


User make assets subfolder in the frontend I have a standard user profile form. But now I would like that the user can upload images in new subfolder and make own subfolder.
Is there any solution or a plugin for this?

No idea if it lets users create subfolders on the front-end, but this is the closest plugin I could find: https://straightupcraft.com/craft-plugins/assets-browser

If that doesn't do it, most likely you'd need to do some custom plugin work to do what you're looking for.


Search results home page title not showing properly but other pages do? Usually Google search results shows the <title> value as the title on the results, but with a CraftCMS website it shows the websites name with a colon and removes the last segment? I've checked on another CraftCMS website and the same thing is happening.

Code: <title>Book Store | City Name | Something</title>

Google Results: (Whats happening currently)

  MyBookCompany: | Book Store | City Name

Google Results: (What it should be)

  Book Store | City Name | Something

All other pages of the website meta title renders properly on their searched page. The DOM shows the code title correctly. Using no plugin and this dates latest CraftCMS version. How do I remove this default behaviour that is happening only on the home page?

Could the Google account holder for the domain have set the listing to use a different value than what's in the title element?

Craft doesn't do anything like this out of the box and the SEO plugins that would change the title value you'd see that in the DOM. Is there a meta tag in the head maybe that Google reads to override the title element?

There's no default front-end templating in Craft CMS so whatever is doing this is most likely either whatever the developer's added to the homepage or layout template or Google itself.


How can I get to a category via the category slug using the ElementAPI I am using the ElementAPI to generate a json response of data based on the value (locations) that was chosen from a drop-down.

I think I have all of the pieces I need, i'm struggling with how to put them all together I think.

twig

{% set locations = craft.categories.group('locations') %}
...
{% for location in locations %}
    <option value="{{ location.slug }}">{{ location.title }}</option>
{% endfor %}

elementapi.php

$slug = craft()->request->getRequiredPost('location');  // chicago
$category = craft()->categories->getGroupByHandle('Locations'); // category group
$location = ??

return [
    'endpoints' => [
        'myfile.json' => [
            'elementType' => 'Entry',
            'criteria' => [
                'section' => 'mysection',
                'relatedTo' => ['targetElement' => $location],
            ],
            'transformer' => function (EntryModel $entry) {
                return [
                    'title' => $entry->title
                ];
            },
        ]
    ]
];

I think (well, I know) I am confused by where "regular" php is and where the ElementAPI takes over. This is returning me data, but I'm not sure if it's just dumb luck or I've actually got something working...

$slug = craft()->request->getRequiredPost('location');  // chicago

$criteria = craft()->elements->getCriteria(ElementType::Category);
$criteria->group = 'Locations';
$criteria->slug = $slug;

$locations = $category = $criteria->find();

return [
    'endpoints' => [
        'myfile.json' => [
            'elementType' => 'Entry',
            'criteria' => [
                'section' => 'mysection',
                'relatedTo' => ['targetElement' => $locations],
            ],
            'transformer' => function (EntryModel $entry) {
                return [
                    'title' => $entry->title
                ];
            },
        ]
    ]
];


Asset Meta Fields vs Section with Asset field + the other fields? Let's say we have products, and some of these products have a Firmware Update file (or several firmware update files) that may be associated with the product entry.

The Firmware file assets will have associated "metadata" for each, including:

Version
Region
Release Date
Notes
Install Instructions

My question is would it be better to add a new section for Firmware, with separate fields for the above (plus associated Product and Firmware Asset Entry), or just have the Asset contain all those fields as metadata on the asset entry itself?

I guess this might be a philosophical question. Maybe it will be flagged as too subjective, but I thought I'd ask.

Personally I would add the fields to the asset. Totally depends on what order you prefer to fill in the data.

Are you going to fill in all the data yourself or a client? If so, ask them what they prefer.


How can I add programmatically a Tag after SAVE_ON event in case of Assets types We have to update the Asset after the SAVE_ON event, and the

Craft::$app->elements->saveElement($asset);

Not seems to be working (it is getting timed out). So what is the best pratice to update the Asset after the save, which event should we use for example auto-tagging?

If we are trying to save the entry, it is working like charm, maybe we should query the asset parent first?

Update some additional findings:
It's turned out it is not so easy to re-save the assets after the SAVE_ON. We need to add additional parameters - based on the class rules:

$rules[] = [['newLocation'], 'required', 'on' => [self::SCENARIO_CREATE, self::SCENARIO_FILEOPS]];
$rules[] = [['tempFilePath'], 'required', 'on' => [self::SCENARIO_CREATE, self::SCENARIO_REPLACE]];

Obviously the goal is to just add some tags/category to the image (eg: getting back the tags data from cloudanary auto tagging interface via the filesystem, so we are not able to use the before save event).
So if we are simply trying to save the $asset it is not going to work, because we do not have newLocation either the tempFilePath is old as well. Instead we have to change the scenario, and save the asset after that (the idea was coming after checking the ElementController)

$element->setScenario(Element::SCENARIO_LIVE);
$element->setFieldValue('fieldHandle', $ids);
Craft::$app->getElements()->saveElement($element);

I do not have better idea for Asset save (specially because the asset itself was saved, and only the fields has to be updated), but this solution is working like charm, and the same logic is applied on the CP. If only the fields are getting updated the ElementController is getting called otherwise the AssetController. Hopes it helps for future reference

A Tag field is like every other relation field. Just insert an array of ids in the field and save the element

$element->setFieldValue('fieldHandle', [1,2,3,4,5,6]);
Craft::$app->getElements()->saveElement($element);

In order to get the current ids and add one, just do

$ids = $element->getFieldValue('fieldHandle')->ids();
$ids[] = 'yourNewTagId';
$element->setFieldValue('fieldHandle', $ids);
Craft::$app->getElements()->saveElement($element);

To Create a new Tag do

$tag = new Tag();
$tag->title = "your new tag name";
$tag->groupId = 1;
Craft::$app->getElements()->saveElement($tag);

// and add it to the element
$element = Craft::$app->getElements()->getElementById(2);
$ids = $element->getFieldValue('fieldHandle')->ids();
$ids[] = $tag->id;
$element->setFieldValue('fieldHandle', $ids);
Craft::$app->getElements()->saveElement($element);

Edit:

Note that I'm using the setFieldValue directly instead of the magic __get and __set methods for a better performance.


Static translations not working on Craft 3 since upgrade from Craft 2 I have upgraded from Craft2 to Craft3 and static translations no longer seem to work.

I have created a folder at the same level as the "vendor" folder called "translations" and have got a folder inside that called "en_us" (base language is en_gb). Inside that folder we have a file called "site.php" and inside that is the following:

<?php

return [
    '£' => '$',
    'USD' => '$',
];

The static translation page (https://docs.craftcms.com/v3/static-translations.html) says: "..To do that, create a new folder in your project’s base directory called translations/, and within that, create a new folder named after the target language’s ID".

I assume that is a typo, but I have tried naming the folder the ID number of the site...

I've also tried renaming the folder to "en-US", "en-us" but nothing seems to work.

Code example for a translation attempt in a template: {{ "£" | t }}.

Any help very gratefully received!

From what i see you maybe have a typo. I think it should be en-GB. At least this is the folder name in the git repo : https://github.com/craftcms/cms/tree/69bafb027b9e2dc9c8dbede5ad6b4da2706f0650/src/translations/en-GB


Server requirements for uploading large images I'm experiencing the problem that I can't upload large images. Very similar to this problem: Craft CMS max image resolution? But I couldn't solve the problem so far.

My first question is: Where do I have to place the php.ini so the upload script knows about it? (My web hosters help pages tell me to upload the file in every directory that need the ini files settings) I've tried /craft/app (next to index.php and Craft.php) and /htdocs (the web root).

Plus: I've tried to upload the exact same images to Craft at another web hoster where it works fine. But the limitations there are even stricter than where the problem occurs).

That means: if the location of the php.ini was right the values of post_max_size, memory_limit and max_execution_time are not the problem. Also it doesn't depend on the file size but on the image resolution.

image1.jpg | 703 x 951 pixels | ~850,000 Bytes → does work
image2.jpg | 2520 x 1680 pixels | ~750,000 Bytes → doesn't work
image2.jpg | save with same resolution as: "image3.jpg" → doesn't work
image2.jpg | save with lower resolution as: "image4.jpg" → does work

Does anyone know what else I could check to solve that problem?

Thanks for any help.

Where do I have to place the php.ini so the upload script knows about it?

In the same folder that Craft's public index.php lives in should be the only place it's required.

You can put a phpinfo.php in that same folder with the contents <?php phpinfo(); and load that page in the browser to see if your php.ini changes have taken affect.

  Also it doesn't depend on the file size but on the image resolution.

That's because there isn't a 1:1 correlation because an images size on disk and how much RAM is required to load that image into memory.

post_max_size, memory_limit and max_execution_time and upload_max_filesize are usually the common culprits when dealing with uploading large files in PHP.


How to get latest entries, after X number? I have a site where I want to feature the latest 5 entries and show the next 10 in a separate list. How would I do this?

The first part would be easy: craft.entries.section('news').limit(5)

But I can't figure out how to bring the next 10. Any suggestions?

In the way you have described that you want to use all the results on the page but just moved and used in chunks you should save a query on the database and use slice over offset.

{% set entriesList = craft.entries.section('news').limit(15) %}

{# Featured #}
{% for entries in entriesList | slice(0, 5) %}
{% endfor %}

{# Other List#}
{% for entries in entriesList | slice(4, 10) %}
{% endfor %}


Tagging and Associating Photos with Entry Type We have hundreds of photos on our theater website from past performances. In order to sustainably manage the relationship between cast members and which photos they were in, we wanted to explore setting up some type of tagging system. Would there be a way to associating a person (Entry type) with a photo (Asset Type) at the asset level? That way, we could query the database for any photos a person is in from their bio page and assemble them into a slider.

Assets can have custom fields just like entries. You can create an entry field for the person section, and add it to the asset source field layout from your asset settings.

You can then use relations to query for the right assets or entries as you see fit!


Passing multiple parameters to the Element API How should I go about passing multiple parameters to the Element API?

The scenario is that I would like to display all my categories for a given section in a form, and allow the user to select categories, and send them to the API. I would like to receive back a json object of all the entries that have the categories assigned.

I am aware that I can dynamically catch url segments, but I'm not understanding how I would pass something like a GET parameter as a segment.

Thanks for the help!

You can fetch GET parameters using HttpRequestService::getQuery() or getRequiredQuery():

'entries-by-category' => function() {
    $categoryIds = craft()->request->getRequiredQuery('categoryIds');

    return [
        'elementType' => 'Entry',
        'criteria' => [
            'relatedTo' => ['targetElement' => $categoryIds],
        ],
        // ...
    ];
},


Sprout Forms Payload Forwarding empty value I have a couple of forms that require payload forwarding. The only problem I'm having is that all the content that should be sent through is empty. I can see the form being submitted to the payload lead and is received but it wont share any information.

Now I'm wondering is this from my end or the leads?

Sprout Forms 3.2.0 added an Integrations API and the previously named 'Payload Forwarding' is now handled via the Custom Endpoint Integration.

The new Integrations feature also improves tracking of Integration submissions so you should have more data to help monitor or troubleshoot if any requests are behaving as expected.

LEGACY ANSWER:

Every API you submit data to is different and Payload Forwarding may need to be implemented differently depending on what service you are trying to submit to.

By default, the data that gets forwarded is in the same format that it would be in if you were submitting it to Craft. Many services may require data to be in a different format, so we'd need to know more about where you are trying to submit the data and how to help troubleshoot further.

See a brief overview of Payload Forwarding in the docs. If you need to submit the data in another format, you could consider overriding how the fields are structured in the templates with Template Overrides.

We do have on our list to refactor the Payload Forwarding API to make customizing the payload for different services more accessible.


Querying all content entries for a page I'm new to Craft CMS and I'm trying to build a new website using Craft. I want my client to be able to change the order of displaying contents of a page by dragging and rearranging them in the Admin panel. So I created a Section called 'Home Page' with type Single and I created few fields with type Matrix and I updated the Entry Type for section Home Page with those new fields. Home Page appeared in the Entries under Single as expected and I was able to update the contents on the matrix fields as well.
Then I created a twig file and used the content entered via Admin to render the home page. So far so good but my client wants to rearrange the fields (I don't know whether I  can call them fields) in the Home Page via Admin by dragging them around and that should be reflected in the rendered homepage.
I thought of creating a subfolder and separate twig files for rendering the entry types in the home page but what I don't know is how I can query the entry types from the entry object in the order in which it's configured via the Admin panel.
My Home Page in Admin now looks like this
Banner
Why Choose Us
What We do
Our Clients
Testimonials

And my client wants to change this to say
Banner
What We do
Our Clients
Why Choose Us
Testimonials

Once they change this, it should be reflected in the rendered home page. Is this possible in Craft?

I think you might be going about this the wrong way. Personally, I'd create a single Matrix or Super Table field and attach that to your home page single. This is far easier for your editors to maintain and doesn't require the entry type's field layout every time you want to rearrange content.
However, to answer your question:
What you're looking for is the field layout definition for your entry type (which is effectively what you're looking at in the screen capture you've provided) and iterate over the fields ($entry->fieldLayout->fields) as necessary, either using a switch statement using the field name for conditional processing or by pulling in an include based on the field's name.
If you decide that the latter is really what you want to do, I'll help with some suggested logic but I'd encourage you to look at the first option before digging into the Craft class reference!


Rich Text Field mailto Option Wondering if there is anything (plugin or otherwise) I can put into my Redactor json file that will generate a mailto option in the insert link dropdown? I can’t seem to find anything on the subject.

I'm not aware of any way to do this in Redactor II other than going into Source view and manually entering the mailto syntax.