What is the correct way to use UserIdentity? I am planning to create a micropub plugin so that any micropub client can post to craft, particularly useful for automatic data logging and mobile clients. But I am trying to work out the best way to authenticate.

I have read through the UserIdentity docs but I was wondering if anybody has an examples of how to use it correctly?

The basic user identity relies on login and password, so you will have to create your own class to represent an identity based on something else, like a token for example:

<?php

namespace Craft;

class TokenIdentity extends UserIdentity
{
    private $_id;
    public $token;

    public function __construct($token)
    {
        $this->token = $token;
    }

    public function authenticate()
    {
        $socialUser = craft()->social->getUserByEncodedToken($this->token);

        if($socialUser) {
            $this->_id = $socialUser->user->id;
            $this->username = $socialUser->user->username;
            $this->errorCode = static::ERROR_NONE;

            return true;
        } else {
            return false;
        }
    }

    public function getId()
    {
        return $this->_id;
    }
}

Then you'll need to create your own user session service to be able to authenticate the user (with a token for example):

<?php

namespace Craft;

class Social_UserSessionService extends UserSessionService {

    private $_identity;
    public $allowAutoLogin = true;

    public function init()
    {
        $this->setStateKeyPrefix(md5('Yii.Craft\UserSessionService.'.craft()->getId()));

        parent::init();
    }

    public function login(Oauth_TokenModel $token)
    {
        $rememberMe = true;

        $this->_identity = new TokenIdentity($token->encodedToken);
        $this->_identity->authenticate();

        // Was the login successful?
        if ($this->_identity->errorCode == TokenIdentity::ERROR_NONE)
        {
            // Get how long this session is supposed to last.

            $this->authTimeout = craft()->config->getUserSessionDuration($rememberMe);

            $id = $this->_identity->getId();

            $user = craft()->users->getUserById($id);

            $states = $this->_identity->getPersistentStates();

            // Run any before login logic.
            if ($this->beforeLogin($id, $states, false))
            {
                // Fire an 'onBeforeLogin' event
                $this->onBeforeLogin(new Event($this, array(
                    'username'      => $user->username,
                )));

                $this->changeIdentity($id, $this->_identity->getName(), $states);

                // Fire an 'onLogin' event
                $this->onLogin(new Event($this, array(
                    'username'      => $user->username,
                )));

                if ($this->authTimeout)
                {
                    if ($this->allowAutoLogin)
                    {
                        if ($user)
                        {
                            // Save the necessary info to the identity cookie.
                            $sessionToken = StringHelper::UUID();
                            $hashedToken = craft()->security->hashData(base64_encode(serialize($sessionToken)));
                            $uid = craft()->users->handleSuccessfulLogin($user, $hashedToken);

                            $data = array(
                                $this->getName(),
                                $sessionToken,
                                $uid,
                                ($rememberMe ? 1 : 0),
                                craft()->request->getUserAgent(),
                                $this->saveIdentityStates(),
                            );

                            $this->saveCookie('', $data, $this->authTimeout);
                        }
                        else
                        {
                            throw new Exception(Craft::t('Could not find a user with Id of {userId}.', array('{userId}' => $this->getId())));
                        }
                    }
                    else
                    {
                        throw new Exception(Craft::t('{class}.allowAutoLogin must be set true in order to use cookie-based authentication.', array('{class}' => get_class($this))));
                    }
                }

                $this->afterLogin(false);
            }

            return !$this->getIsGuest();
        }

        Craft::log('Tried to log in unsuccessfully.', LogLevel::Warning);
        return false;
    }
}

This code comes from a plugin which is still under development so don't take for granted it's all secure or the best way to achieve this, but hopefully it will help you get started !


Craft Installation - Getting a Forbidden Error A forbidden error appears and can't get it to disappear. I've gone through the installation process several times and everything else works.

When I load the URL "test.craft.dev", I get back "Forbidden: You don't have permission to access / on this server."

Things I've tried:

1) db.php

$craftPath = '../craft';

2) folder structure

/craft/..
/public/index.php

Any help would be greatly appreciated.

When I get this error it is usually because the top craft directory isn't readable. When you unzip the original craft zip file, you get something like this:

drwx------@ 5 m  staff       170 Jul  8 14:47 Craft-2.1.2563

And that top directory (the one that contains craft and public) needs to be readable by apache.


`routes.php` config example I want to move some permanent routes from the admin to my routes config file so that they can be version controlled.

in the admin...
news-sort/month/<year>/<month> ....
news-sort/tag/<tag> ....
news-sort/author/<*>

Do these look ok, not 100% sure on the variable and regex etc.

'news-sort/month/(?P<year>\d{4})/(?P<month>\d{2})' => 'news-sort/index',
'news-sort/tag/(?P<tag>[a-zA-Z0-9._%-]+)' => 'news-sort/index',
'news-sort/author/(?P<author>[a-zA-Z0-9._%-]+)' => 'news-sort/index'

The simplest way to transform dynamic routes into advanced routes, is to go to your craft_routes table and copy it out of urlPattern:

Example:

If you have set this in your backend:
news-sort/month/<year>/<month>

You'll find this in urlPattern:
news\-sort\/month\/(?P<year>\d{4})\/(?P<month>(?:0?[1-9]|1[012]))

Just remove the escaping \, and you've got your regex:
news-sort/month/(?P<year>\d{4})/(?P<month>(?:0?[1-9]|1[012]))


All fields disappearing except 'Title' after saving All other fields disappear except the 'Title' field after I save a large block of text with a lot of links in the body (richtext) field.

I can't seem to pinpoint it on to anything specific, this is what I'm putting inside the 'Source' of the richtext http://pastebin.com/jiyA6xii

Any help would be greatly appreciated.

I had a similar problem with disappearing fields in the admin interface, and found it seemed to be something to do with the xdebug PHP extension. Disabling that fixed the problem and the fields reappeared:

sudo php5dismod xdebug
sudo service apache2 restart

The problem in this case is actually to do with reaching a nesting limit, so if you do want to use xdebug, an alternate fix is to bump up the max nesting limit in xdebug's ini file (or php.ini), eg:

xdebug.max_nesting_level=200


Can you add duplicates fields in a structured section's GUI? Is there a way to duplicate fields when creating "structures" in the visual editor. If I wanted to add four simple textfields, it appears I can't just drag-and-drop four textfields in and give them IDs as that field disappears.

i.e. If I have four tabs with headlines... would I need to create four separate fields called "headline"?

An entry type can only use a field once, regardless the tab. But you can reuse the field in other entry types of that same section or reuse it in other sections.

Keep in mind, that you (currently [*]) always have the same field settings shared with each instance you use it. Meaning that you'll always end up with the same field name and instructions, which sometimes (I'd say often) is a deal breaker for reusability.

[*]: if I remember this right, I already made P&T aware of this and made a feature request


How does the negative (not) conditional work in Twig? If I write:

{% if entry.section not 'Homepage' %}Blabla {% endif %}

this results in the error:

  Unexpected token "operator" of value "not" ("end of statement block"
  expected)

But if I write:

{% if entry.section != 'Homepage' %}Blabla {% endif %}

It works.

In the twig docs there is no mentioning of != as an operator but it seems to be working just fine. Is != a craft specific operator?

So whats the difference between not and != ?

Twig != is a comparison operator.

  The following comparison operators are supported in any expression: ==, !=, <, >, >=, and <=

You can use != to compare any two things that php lets you compare, and what you get back is a boolean.

Twig not is a logic operator. (so are and and or)

  not: Negates a statement.


How would I omit zero value decimals in a number format? Say I have {{ item.width }} and {{ item.height }} which are number fields with 2 decimal places.
In my template I have this:

Dimensions: {{ item.width }} x {{ item.height }} in.

Which will output like this:

Dimensions: 8.50 x 11.00 in.
Dimensions: 5.00 x 7.00 in.
Dimensions: 4.25 x 6.50 in.

How would I drop the decimal places that are not used?  Like this:

Dimensions: 8.5 x 11 in.
Dimensions: 5  x 7 in.
Dimensions: 4.25 x 6.5 in.

This can be done with Twig's trim filter. It works just like PHP's trim function.

{{ item.width|trim('0','right')|trim('.','right') }}


How can I display a message after login? When a user logs in, I want to display the message "Login Success" or an error message "Username or Password is incorrect" if a user enters the wrong details.

What is the best method for displaying these messages when a user logs in and logs out? I am not sure how to write the correct way using getFlash?

You can achieve this using a plugin and the UserSessionService.

craft()->on( 'userSession.onLogin', function( Event $event ){
  // Sets the flash message on log in
  craft()->userSession->setFlash( 'message', "You've been logged in" );
});

craft()->on( 'userSession.onLogout', function( Event $event ){
  // Sets the flash message on log out
  craft()->userSession->setFlash( 'message', "You've been logged out" );
});

And then in your template you can see of a flash message exists and print it out.

{% set message = craft.session.getFlash( 'message' ) %}

{% if message %}
  {{ message }}
{% endif %}

The message for the incorrect login details will be handled by Crafts login controller. Take a look at the example front end log in page in the docs to see how this is handled.


User activation link issue I have a local craft.dev server running MAMP, and a public server (mysite.com), that both access the same database (on the public server). I then have some environmentvariables in general.php that makes this work smoothly (setting siteUrl and basePath for the different environments).

However, this doesnt seem to work if I access my public servers Craft CP, and add a new user. The activation link won't work on the users end. If I check Craft CPs General Settings it says the siteurl is craft.dev (even when I'm on mysite.com/admin), so that might be the problem, I guess.

This is how I have setup my general.php:

'.dev' => array(
    'devMode' => true,
    'environmentVariables' => array(
        'siteUrl' => 'http://craft.dev/',
        'basePath' => '/Users/foo/'
    )
),

'mysite.com' => array(
    'cooldownDuration' => 0,
    'environmentVariables' => array(
        'siteUrl' => 'http://mysite.com/',
        'basePath' => '/home/mysite_ftp/www/'
    )
)

Would it make sense if I visit mysite.com/admin, change the CPs general settings siteurl to mysite.com/, add the user, and then change siteurl back to craft.dev? Would the activation link work on the users end then?  And, can I do any harm by changing this siteurl-setting (just to give it a try)?

I don't know if this is relevant for the Email Service, but you should use the (new since Craft 2.0) siteUrl config setting (recommended):

'.dev' => array(
    'siteUrl' => 'http://example.dev/',
    'environmentVariables' => array(
        'siteUrl' => 'http://example.dev/',
        'serverPath' => '/Users/foo/'
    ),
),

'mysite.com' => array(
    'siteUrl' => 'http://example.com/',
    'environmentVariables' => array(
        'siteUrl' => 'http://example.com/',
        'serverPath' => '/home/mysite_ftp/www/'
    ),
),

// ...

Or you set the Site URL setting in Settings → General to {siteUrl} (the custom siteUrl variable you set in environmentVariables).


Can notes on line items be updated on checkout? Currently, a user has to click update on each line item to save changes to quantity or a note. The quantity might make sense to the user as it updates the price, but a user could assume that the note would just need to be filled out.

Wondering if there's a simple way to allow the user to fill out notes without clicking update and have them save.

I use ajax autosave to achieve this, and ajax update the cart in the background (for notes, but also pretty much everything else).

I essentially use the recipe from:
from https://github.com/geniuscarrier/autoSave/

In the callback function that is called after the autosave event, I post the to the update cart controller.  The JSON object that comes back from an ajax request is quite complete and let's your update your cart page / totals etc from there.

Personally I hate non dynamic carts with update buttons, so I have ajaxed all cart operations, including qty changes, removals, line item and order notes etc.


Replacement for deprecated EntryRevisions service Client has a custom Craft plugin for managing their bespoke publication workflow on a large website. Content creators create new or updated content that is saved as drafts, then inspected and approved by editors before publication.

This plugin makes heavy use of the EntryRevisions Service Which has been deprecated in CraftCMS 3.2. For example, the plugin often fetches a draft instance by ID before performing other actions (publish/edit/delete), using information in the draft to create a notification email, or getting the contents of the draft for review. The plugin has it's own tables the track drafts by it's ID alone, so it's my primary means of looking up drafts.

The API documentation says to use the EntryQuery API instead, but the docs don't mention how to get a draft or revision.

Does anyone know how drafts are fetched and worked with going forward?

Revisions and Drafts are first-class citizens of the Element world in Craft 3.2.

So for your example:

  The plugin has it's own tables the track drafts by it's ID alone, so it's my primary means of looking up drafts.

This is what you would do:

$draft = Entry::find()
    ->draftId(123)
    ->one();


Cookiebot finding TS# cookie As part of the new GDPR requirements in europe I've used cookiebot to show visitors what cookies we use on our site.

It's managed to show us what all but 1 cookie is used for. The cookie is called TS# and in their example stores this information:
0ei8sug22mj561h32e087mb5f2

The cookiebot report doesn’t mention CraftSessionId which has this data:
p2q9d364sf2abu1mmd5vi8rd54

May be a coincidence but they're both 26 characters long.

Does anyone know what the TS# cookie is used for, if it is a Craft CMS cookie?

Craft doesn't natively set a cookie named TS#, so it's either coming from something in your front-end templates or possibly from a plugin you've got installed.

You can read about the CraftSessionId cookie and all other cookies that Craft uses by default here: https://craftcms.com/support/how-does-craft-use-cookies


Problem with Site Running Both HTTP & HTTPs So we're trying to set-up a site to run both HTTP & HTTPs version in parallel for SEO auditing before making the full switch to HTTPs. We followed Ben's answer on this SE question to make it work: https://craftcms.stackexchange.com/a/4734/57.

The behavior we're seeing after implementing Ben's recommendation are that we can access both the http and https version of each page but a click on any link in the site populated by Craft templates (nav, blog overview page linking to other entries, etc.) takes us to the HTTP version of the page. So for example, if you're on https://example.com, a click on a nav link takes you to http://example.com/click rather than https://example.com/click. However, if we have a root relative link that was added manually through the control panel, that takes you to a version of the page consistent with the protocol of the current page. Basically, Craft is treating all links as if they're HTTP, even if you're on the secure version of the site.

We would like the site to function where if you're on the HTTPs version, a click on any link keeps you on the HTTPs version. Same goes for if you're on the HTTP version, any link click takes you to another HTTP page.

Is there a way to configure Craft to make that happen?

Here are the contents of our craft/config/general.php file:

<?php

/**
 * General Configuration
 *
 * All of your system's general configuration settings go in here.
 * You can see a list of the default settings in craft/app/etc/config/defaults/general.php
 */

// SEE http://buildwithcraft.com/docs/multi-environment-configs for info

// Ensure our urls have the right scheme
define('URI_SCHEME',  ( isset($_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] == "on" ) ? "https://" : "http://" );

// The site url
define('SITE_URL',    URI_SCHEME . $_SERVER['SERVER_NAME'] . '/');

// The site basepath
define('BASEPATH',    realpath(CRAFT_BASE_PATH . '/../') . '/');

return array(

  // DEFAULT
  '*' => array(
    //'isSystemOn' => false,
    'omitScriptNameInUrls' => true,
    'cpTrigger' => 'discover',
    'addTrailingSlashesToUrls' => true,
    'siteUrl' => SITE_URL,
    //'devMode' => (preg_match('/dev|xip|staging/', $_SERVER['HTTP_HOST']) ? true : false),
    'devMode' => false,
    'pardotUserName' => "FILLER TEXT",
    'pardotPassword' => "FILLER TEXT",
    'pardotUserKey' => "FILLER TEXT",
    //'backupDbOnUpdate' => false,
    'generateTransformsBeforePageLoad' => true,
    // 'cacheDuration' => false,
    'defaultImageQuality' => 90,
    'caseListPagination' => 6,
  ),
  // Example dev
  'example.dev' => array(
    'devMode' => true,
    'caseListPagination' => 2,
  ),

  'example.svn.dev' => array(
    'devMode' => true
  ),

  'local.example.com' => array(
    'devMode' => true,
    // 'enableTemplateCaching' => false // Only work on Craft 2.4 and later
  ),
  'environmentVariables' => array(
    'siteUrl' => SITE_URL,
    'basePath' => BASEPATH
  ),
);

Thanks!

What web server are you running? I ask because IIS will define the $_SERVER['https'] variable even if the site is being accessed via HTTP (it's value will be 'off') and Ben's answer is only checking if the $_SERVER['https'] variable is present.

One solution is to add a further check that $_SERVER['https'] == 'on'

Try updating this:

// Ensure our urls have the right scheme
define('URI_SCHEME',  ( isset($_SERVER['HTTPS'] ) ) ? "https://" : "http://" );

to this:

// Ensure our urls have the right scheme
define('URI_SCHEME',  ( isset($_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] == "on" ) ? "https://" : "http://" );


How can I create a States drop down? Working with the Commerce example templates.
The example template uses javascript to populate the States which is based on the selected Country. The code for the Country and State select field:

Country
<select class="address-country" name="{{ modelName }}[countryId]">
    {% for key, option in countries %}
        {% set optionValue = (model ? model.countryId : '') %}
        <option value="{{ key }}" {% if key == optionValue %} selected{% endif %}>{{ option }}</option>
    {% endfor %}
</select>
{% if model and model.getErrors('countryId') %}

{{ model.getErrors('countryId')|join }}

{% endif %}

State
{% set options = (model and states[model.countryId] is defined ? states[model.countryId] : []) %}
<select id="{{ modelName }}-stateId" data-modelname="{{ modelName }}" class="address-stateId {% if options|length == 0 or (model and model.stateName) %}hidden{% endif %}" name="{{ modelName }}[stateValue]">
    {% for key, option in options %}
        {% set optionValue = (model ? model.stateId : '') %}
        <option value="{{ key }}" {% if key == optionValue %}selected{% endif %}>{{ option }}</option>
    {% endfor %}
</select>
<input type="text" data-modelname="{{ modelName }}" id="{{ modelName }}-stateName" class="address-stateName {% if options|length > 0 or (model and model.stateId) %}hidden{% endif %}" {% if model and model.stateName %}name="{{ modelName }}[stateValue]" value="{{ model.stateName}}"{% endif %}>

All I'm looking for is a drop down for US States no other Countries will be used. I like to keep the 'model' in place though.

The javascript:

{% includejs %}
var states = {{ craft.commerce.statesArray|json_encode|raw }};

$('select.address-country').change(function ()
{
    // get the value of the selected country.
    var cid = $(this).val();
    var $states = $(this).closest('.addressBox').find('select.address-stateId');
    var $stateName = $(this).closest('.addressBox').find('input.address-stateName');
    $states.find('option').remove();

    if (states.hasOwnProperty(cid))
    {
        // We have states for this country, show the states drop down.
        $states.removeClass('hidden');
        $states.attr('name', $states.data('modelname')+'[stateValue]');

        // We have states for this country, hide the stateName input.
        $stateName.removeAttr('name');
        $stateName.addClass('hidden');
        $stateName.val('');

        // Add all states as options to drop down.
        for (var id in states[cid])
        {
            var state = states[cid][id];
            var $option = $('<option/>');
            $option.attr('value', id).text(state);
            $states.append($option);
        }

    }else{
        // hide the states dropdown, since this country has none.
        //$states.addClass('hidden');
        //$states.removeAttr('name');

        // show the stateName
        $stateName.removeClass('hidden');
        $stateName.attr('name', $stateName.data('modelname')+'[stateValue]');
    }

});

$('select').addClass('form-control input-sm');{% endincludejs %}

I ended up just hardcoding based on the US countryId of 233.

{% set states = craft.commerce.statesArray["233"] %}

Then simplified my template like this:

<select name="{{ 'model' ~ '[stateId]' }}" required>
     {% for key, state in states %}
          <option value="{{key}}">{{state}}</option>
     {% endfor %}
</select>


Missing 'Plugin Store' tab in admin panel I'm using Craft 2.7.9 and can't access the Plugin Store page. I've searched for fixes here but didn't find anything helpful.

I've tried to access it directly via http://localhost:8888/admin/plugin-store but I got an error:

  Page Not Found The requested URL was not found on this server.

However, I'm not sure if the link is the same for Craft 2? That one I know from Craft 3.

Any ideas why is it missing? Need to install and test one plugin, tried to upload it manually to plugins folder but unfortunately that didn't work too.

Thanks!

The Plugin Store is a feature introduced in Craft 3, so isn't available in previous versions.

See: Missing Plugin Store Navigation on Craft 3 Admin Section
And: Announcing Craft 3 Blog


Ajax Post to Plugin Controller I have been stuck on trying to make an ajax call to a custom plugin controller in Craft 2 for a few days after trying everything from following the documentation for Craft 2 as well as looking up other posts that basically reiterate what the documentation says, but nothing seems to work. According to the documentation for Craft 2, I should be able to use:

[PluginHandle]/[ControllerName]/[ActionName]

in a hidden field. I've even tried using the full method name, actionGetLocations, just to rule that out. Here is what I have:

<input type="hidden" name="action" value="/actions/googleMap/getLocations">
<input type="hidden" name="redirect" value="{{ siteUrl }}map-test">

Here is my controller:

<?php

namespace Craft;

class GoogleMap_MapController extends BaseController
{
    public function actionGetLocations()
    {
        $this->requireAjaxRequest();

        return $this->returnJson([
            'success' => [
                'state' => "This would be states",
                'locations' => "This would be locations"
            ]
        ]);
    }
}

My controller file is named GoogleMap_MapController.php to follow the naming scheme. I also have my ajax request, which needs to be written in vanilla javascript for this site:

var xhr = new XMLHttpRequest();
            xhr.open('POST', '/actions/googleMap/getLocations');

            xhr.onreadystatechange = function() {
                if(xhr.status === 200) {
                    console.log(xhr);
                }
                else {
                    console.log("The request failed, returned status of " + xhr.status);
                    console.log(xhr);
                }
            };

            xhr.send(data);

I get a 404 error for page not found, which makes sense since it's not really a page, but the documentation says that it will attempt to determine if the request URL is an action first. I tried changing the ajax call to post to '/' instead, but that returns the HTML from the page '/' successfully, which is not what I'm trying to get at all. I've tried sticking my hidden input tags in a form tag, however the submit causes the page to redirect to this non-existent route. I added in onsubmit="event.preventDefault();" to my form tag, and while it doesn't redirect, I still get a 404 error response. I'm completely at a loss at this point any help is greatly appreciated.

Based on your controller's class name, I believe you need to POST to this endpoint...

/actions/googleMap/map/getLocations


Filter entries by multiple categories I am trying to set up a form with checkboxes that allows users to filter entries by selecting multiple categories, but I am not quite getting it right.

Currently this is my form:

{% set subcategoryParam = craft.request.getParam('subcategory') %}
{% set subcategories = craft.categories.group('partnerAreas').find() %}

<form action="{{ craft.request.url }}">

  {% for subcategory in subcategories %}
    <input type="checkbox" value="{{ subcategory.slug }}" id="{{ subcategory.slug }}" name="subcategory" {{ subcategory.slug in subcategoryParam ? 'checked'}}>
    <label class="label__checkbox" for="{{ subcategory.slug }}">
      {{ subcategory.title }}
    </label>
  {% endfor %}

  <button type="submit">
    Search
  </button>
</form>

Submitting this form gets me URL query strings like this:

?subcategory=sourcing-local-products&subcategory=communication

When I am using craft.request.getParam('subcategory'), only the last selected subcategory gets picked up (as you would expect).

I've tried setting the name on the checkbox field to subcategory[], but that gets me an array to string conversion template error and the URL query string then looks like this:

?subcategory%5B%5D=sourcing-local-products&subcategory%5B%5D=communication

What do I need to do to get a comma separated list for the subcategory parameter like this:

?subcategory=sourcing-local-products,communication

And once that is working, how do I then get all the entries that have any of the selected categories assigned via a Matrix field?

This is what I've currently got:

{% set subcategoryParam = craft.request.getParam('subcategory') %}
{% set selectedSubcategories = craft.categories.slug(subcategoryParam) %}
{% set entries = craft.entries({
  section: listingType,
  relatedTo: {
    targetElement: selectedSubcategories,
    field: 'involvementAreas.area'
  }
}) %}

But I imagine that's not quite right if I want to account for an array of selected categories...

I had to get this working just the other day. Here is what I did:

{# Get the relevant entries #}
{% set categoryQuery = craft.request.getParam('category') %}
{% set categories = craft.categories.group('sectionName').slug(categoryQuery) %}

{# Set the search parameters #}
{% set searchParams = {
    relatedTo: categories,
    section: 'sectionName'
} %}

{# Get the relevant entries #}
{% set relevantEntries = craft.entries(searchParams) %}

In the form I have:

<form action="">

{% for category in craft.categories.group('services') %}
    <input id="{{category.slug}}" type="checkbox" name="category[]"  value="{{ category.slug }}" {{ category.slug in categoryQuery or categoryQuery == null  ? 'checked'}}>
    <label for="{{ category.slug }}" >{{ category.title }}</label>
{% endfor %}

</form>

This seems to work for me.


Any ID I could reference in sections I created a section for appointment record (channel type). Each appointment record has different fields, i.e. customer name, phone#, address, etc... I would like to set a unique appointment_record_id (Numeric, i.e. 234) for each record.  Is there any way to create it?

If you were to do this on entry save, it'd be much easier/cleaner.

You'd write a simple plugin that listened to the onBeforeSaveEntry event.

The plugin would check the isNewEntry param to make this this is a new entry and not an existing one.

If it's new, you could generate a random numeric value with mt_rand, assign it to your custom field and left the request continue so Craft can save it to the entry.

A string field for the unique identifier would be better though, since mt_rand will not always produce unique numbers (for unique numbers you'd need to keep a separate database table and obtain id's within a transaction). If you'd use strings you could use uniqid('', true) if you deploy on a single server, or better use a uuid/guid.

If you didn't do it on save, but wanted to be auto-populated when someone clicked "New Entry", you'd have to do something much more hacky like have JS loaded load, try to target the field in the particular section with JavaScript and inject the random number into the DOM.


Eager load Imager transforms in Craft Commerce I am using Imager to create my image transforms. I am on a category page and I want to list all of the products.

I did a quick .with(['cf_shop_assets']) optimization and wanted to continue with the image transforms.

Frankly, I don't know where to start?

{% set products = craft.commerce.products.relatedTo(category).with(['cf_shop_assets']) %}
{% if products|length %}

        {% for product in products %}

        {% set variants = product.variants %}
        {% set variant = product.defaultVariant %}

                    {% set image = product.cf_shop_assets[0] ?? null %}
                    {% if image|length %}
                        {% set transformedImage = craft.imager.transformImage(image, {
                            width: 300,
                            quality: 90,
                            format: 'jpg',
                            bgColor: '#EFEFDE',
                            effects: { sharpen: true }
                        }) %}

                    {% endif %}

{{ product.title }}

            […]

        {% endfor %}

{% endif %}

The code works, but it only saves about 5 queries.

Would somebody be so kind to show me how to eager load Imager transforms?

I need Imager because I don't want to use transparent PNGs. There's no native way to transform a PNG to JPG and adding a background color.

Is this even possible?

Eager loading is used to reduce the number of database queries. Imager doesn't store any data in the database, it's completely file-based, so it's not relevant to use eager-loading in relation to it.


Replace substring in string with variable named as substring? Could you help me with something?

In a frontend template, I'm trying to go through the string, find all substrings between double curly brackets {{ something }} using regular expressions and replace them with field values that have the substring in the name. I want it to work dynamically.

i.e. replace string {{ something }} with value of field {{ entry.something }}, replace string {{ something-else }} with value of field {{ entry.something-else }} ...etc.

I tried the replace filter, and I'm able to find the strings between curly brackets, but I don't know how to replace them with actual fields values.

Thanks

It sounds like you'd be better off using Yii's Message Translations for this, if that's possible in your situation. They are what powers Craft's |t / |translate filter:

{{ "String with {something} and {somethingElse}"|t('site', entry) }}

With this, {something} and {somethingElse} would be replaced with the string values of entry.something and entry.somethingElse.

You can also pass an array for more complex substitutions:

{{ "String with {something} and {somethingElse}"|t('site', {
    something: entry.something,
    somethingElse: entry.somethingElse,
}) }}


Search for entries where a field value is between multiple ranges of numbers I currently have this working for a single range of numbers, but I can’t figure it out for multiple ranges. I currently have it set up like this for one range, and it works. myFieldHandle: ['and', '> 0', '< 10'].

I'm not sure if you can do this in the same query but you can use two queries, one for each range, and then merge them, something like this:

{% set range1 = craft.entries({myFieldHandle: ['and', '> 0', '< 10']}) %}
{% set range2 = craft.entries({myFieldHandle: ['and', '> 20', '< 30']}) %}
{% set entries = range1 |merge(range2) %}


Section entries - order by random I was wondering if it's was possible to order section entries by random.

Example:

{% for entry in craft.entries.section('team').type('mainPeople').order('title random)) %}

You can use MySQL's RAND() function inside your order method:

{% for entry in craft.entries.section('team').type('mainPeople').order('RAND()') %}


Internal Server Error for admin login and dashboard I deployed a Craft 3 site and the site is fine, however when I try and go to /admin to login I get a Craft "Internal Server Error - Server Error" message and can't access the dashboard.
Any ideas where to look?

Thank you!

To get some ideas we'll need more information. I suggest

Go to storage/logs folder
Hit from that directory tail -f *
Then go to your chrome and try to access your : admin page
Go back to your tail -f you will see some error

Tell us more about the error your find.


RelatedTo query with length criteria I am trying to get results from a relatedTo query, but only if there are more than say 1 results. Right now I am using two queries to achieve this, like so:

{% set authors = craft.entries({
    section: 'authors',
    with: [
        'authorImage',
    ],
    limit: 18,
    order: 'authorSurname asc'
}) %}
{% for author in authors %}
    {% set relatedEntries = craft.entries.section('articles').sponsoredAuthor('= 0').relatedTo(author) %}
    {% if relatedEntries|length > 1 %} ... {% endif %}
{% endfor %}

But this messes up pagination (amongst other things) because the loop will iterate no mater if the related entries have more than 1 result. So I was wondering if it is possible (without using a custom query) to have the same result as a single query, so that the results match the number of the items in the loop and pagination does not break. Something like:

authors = craft.entries.section('authors').relatedTo('articles where articles results > 1)

or something like that. Is it possible?

Thanks!

The only way I can think to do this is with a plugin that tracks the relation count, storing it as a custom field.

First create a new Number custom field called “Total Articles” (handle: totalArticles). Assign it to your Authors field layout.

Then create a new plugin. Put this in the primary plugin class’ init() method:

craft()->on('entries.saveEntry', function(Event $event) {
    /** @var EntryModel $entry */
    $entry = $event->params['entry'];

    if ($entry->getSection()->handle === 'articles') {
        // Update author relation counts
        foreach ($entry->relatedAuthor as $author) {
            $criteria = craft()->elements->getCriteria(ElementType::Entry);
            $criteria->section = 'articles';
            $criteria->relatedTo(array(
                'targetElement' => $author,
                'field' => 'relatedAuthor'
            ));
            $totalArticles = $criteria->total();

            craft()->db->createCommand()->update('content',
                array('field_totalArticles' => $totalArticles),
                array('elementId' => $author->id));
        }
});

Finally, from your template, you can fetch only the authors that have at least 2 articles like so:

{% set authors = craft.entries({
    section: 'authors',
    totalArticles: '>= 2',
    with: [
        'authorImage',
    ],
    limit: 18,
    order: 'authorSurname asc'
}) %}


Where can I download previous versions of Craft? Auto-updating is great and all, but sometimes you need to roll-back to a previous version or build of Craft for whatever reason.  Where can you download these?

In Craft 2:

You can download previous versions of Craft from https://download.craftcms.com.

Previous versions and builds of Craft are available with the following URL format in both zip and tar.gz versions:

http://download.craftcms.com/craft/{version}/{version}.{build}/Craft-{version}.{build}.zip (or .tar.gz)

For example, if you wanted Craft 2.1 build 2557 in tar.gz format, it would be

http://download.craftcms.com/craft/2.1/2.1.2557/Craft-2.1.2557.tar.gz

Note that downloading Craft releases directly still binds you to Craft’s license agreement, and keep in mind that Craft does not support rolling back to previous versions automatically.

If you’ve already updated your site past a certain release and want to go back to it, you’ll need to find and restore a database backup that was created with the version you’re going back to.

In Craft 3:

You can download previous Craft 3 versions in several ways:

From pre-built packages in this format:

http://download.craftcms.com/craft/{majorVersion}/Craft-{majorVersion}.{minorVersion}.zip (or .tar.gz)

For example:

http://download.craftcms.com/craft/3.0/Craft-3.0.26.1.zip (or .tar.gz)

Directly from the Craft Github repo release page
Since Craft 3 is Composer based, you can modify your composer.json's craftcms/cms line to install the previous version you're looking for.


CSS will not load Craft 3 + MAMP I'm a UX designer with some front end skills (though a complete novice with server config and Craft). I'm hoping someone can help me with something that seems rather basic.

Setup:
Mac Book Pro running High Sierra (10.13.5).
Using MAMP 4.4.1 (free version)
PHP 7.2.1, MySQL, and Craft 3.
The site loads in a browser when I visit: http://localhost:8888/.

My craft files are here: Macintosh HD/Applications/MAMP/htdocs/.

The template file in question is here: Macintosh HD/Applications/MAMP/htdocs/templates/_layouts/base.html

In the base.html file, in the head section, I am attempting to link to several CSS files. Here's the entire head section:

<head>
    {% block head %}
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta charset="utf-8">
      <title>{% if title is defined %}{{ title }} - {% endif %}{{ siteName }}</title>
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      {% css %}
        <link rel="stylesheet" type="text/css" href="{{ siteUrl }}src/css/typeplate.css">
        <link rel="stylesheet" type="text/css" href="{{ siteUrl }}src/css/grid.css">
        <link rel="stylesheet" type="text/css" href="{{ siteUrl }}src/css/screen.css">
      {% endcss %}
    {% endblock %}
</head>

The CSS files in question are here: Macintosh HD/Applications/MAMP/htdocs/src/css.

The Problem:
When I load the home page, the CSS does not load.

Things I've Tried:

I've tried removing the siteURL bit, and just hardcoding things
instead (like this: http://localhost/src/css/typeplate.css), and I
get 404 errors for the 3 css files under the network tab in Chrome developer tools.
I've tried removing the {% css } brackets around the stylesheet links, and the network tab in Chrome dev tools just tells me "failed" when the links are hard coded. When the links have {{ siteUrl}} in them, I can see the browser looking for the files at www.mywebsite.com/src/css/typeplate.css. But the files aren't currently there - this is a local dev site only.
I've tried changing the dev siteUrl in general.php from "null" to
"http://localhost/", and the web page stops loading altogether.
I've tried different hard coded URL's, like
(../src/css/typeplate.css).
I've searched StackExchange for similar problems, but I can't seem to make sense of any of the answers.

Can anyone help? Thank you so much in advance.

After some searching, I decided to move my src/ folder into the web/ folder, since Craft seems to be looking only there and not at anything above that directory. Then, my CSS links were updated to relative paths like this: src/css/typeplate.css. And that worked.


Force browser to download latest CSS file Is there any simple way to automatically add a version number when referencing a CSS file?

Example: <link href="style.css?v=VERSION-HERE" rel="stylesheet" type="text/css">

Version could be a timestamp when the style.css was last modified or something like that.

The reason for this is that I often have to tell my clients to force the browser to reload because they don't see the latest changes I've made in style.css.

If it matters, I use Deploybot and github.

There are several plugins that can do this.

With my plugin Stamp, you can add a timestamp to the filename or path in the following formats:

<script src="/assets/build/js/1399647655/scripts.js"></script>
<script src="/assets/build/js/scripts.1399647655.js"></script>
<script src="/assets/build/js/scripts.js?ts=1399647655"></script>

The last one, which is the one you're looking for is made with:

<script src="{{ craft.stamp.er('/assets/build/js/scripts.js', 'query') }}"></script>

You can also get only the timestamp, and use it however you want, like this:

{% set timestamp = craft.stamp.er('/assets/build/js/scripts.js', 'tsonly') %}

It's worth noting that you'd ideally want to not use a query string for this, as various frontside proxies could ignore it. But, you need to be able to set up the proper url rewriting in your webserver for the filename and folder versions, so that might not always be possible.

There is also Cache Buster from Focuslab which can add a query string, but also supports file revisioning based on a manifest file.

And there's Asset Rev from Club Studio which is primarily for file revisioning based on a manifest file, but falls back to a query string.


Google XML Sitemaps plugin I would like to know that do we have Google XML Sitemaps plugin for Craft CMS. If yes is there an tutorial that how I can use it. I would like to use it for SEO purpose so that Google can easily crawl my website. A short explanation or video tutorial would be really nice. Thanks in advance.

There are several plugins that can dynamically generate XML sitemaps for you on your Craft CMS site.

Note that Google XML Sitemaps are not specific to Google. Google supports the standard sitemap protocol which is also used by Microsoft and Yahoo!.

I'll highlight two commercial plugins that support generating sitemaps for all native URL-Enabled Content which includes Entries, Categories, and Commerce Products:

Sitemap - Sitemap by Put Your Lights on is a plugin that focuses specifically on creating an XML sitemap for you.
Sprout SEO - Sprout SEO is a more comprehensive plugin for a wider range of SEO needs, which includes search, social sharing, sitemaps, and redirects. Sprout SEO will generate an XML sitemap for you and supports large sitemaps, multi-regional, and multilingual sitemaps. Sprout is also extensible and developers can add Sitemap support for custom URL-Enabled Sections.

There are also several other free sitemap plugins. A search for 'sitemap' in the plugin directory on Straight Up Craft can point you in the direction of several of those.


Session Cleanup in Craft Just had an e-commerce site go down due to Craft's custom way of handling Sessions. The session directory never gets cleaned up, causing the sessions folder to be littered with tens to hundreds of thousands of orphaned files, causing my server to run out of inodes. PHP has a built in utility to deal with this, but that doesn't work since Craft sets a custom session directory. Looking for a good cron job or other utility that will automatically clean this folder up automatically.

Also, curious if there is work being done on Craft to fix this issue by default. I wonder if the reason it hasn't become as big of an issue as it seems it is (only found a handful of people mentioning it on the Google Plus page), is because Craft hasn't been out long enough for some sites to experience this yet, but they may soon. It took about 4 months for the session directory to get too full on a pretty small hard drive, so I wonder if a number of other sites with bigger hard drives currently have this issue behind the scenes, and haven't experienced any problems yet, but will soon.

Apparently PHP's garbage collection does not work when you've set a custom PHP session save path.

Lame.

If you set the overridePhpSessionLocation config setting to false, Craft will go with whatever path Apache/PHP is configured to save sessions to. If you're not on shared hosting, then it's a perfectly safe change, too.

Setting that to false on a site that is on shared hosting has its own security implications.

  curious if there is work being done on Craft to fix this issue by default.

We're discussing what we can do in Craft itself to help with this.


Archive Not Returning Correct Date Variable I'm using the technique for creating an archive that's in the Craft docs: https://craftcms.com/support/entry-archive

I'm archiving by day, so my code looks like this:

{% set agendaEntries = craft.entries.section('agenda').status('live,pending,expired').limit(null) %}

{% for day, entriesInDay in agendaEntries | group('postDate.day') %}

{{ day | date('Y-m-d') }}

    {% for entry in entriesInDay %}

          {# entry data #}

    {% endfor %}

{% endfor %}

The looping and grouping (heh) works great, but the {{ day }} variable doesn't correctly output the date, instead I get the day-before-Epoch date (1969-12-31).

I don't really understand how the for loop even knows what the day variable is, so I don't know how to troubleshoot.

Your postDate.day will output the number of the day in the month so if your entries postdate is 02.dd.yyyy your output is 2. Your array index will be something like [2, 3, 5, 12, 31] thus these values will be converted from the timestamp into a readable day with<h2>{{ day | date('Y-m-d') }}</h2>. The first timestamp (0) is 01.01.1970 because of your timezone you'll see only values around this date since you convert all the day numbers from 1-31 as timestamps to your given format.

In case you did not know: the day variable represents only the keys of the array and with | group('postDate.day') you define the keys. I think your goal is to have keys like [ 'Monday', 'Tuesday'.... 'Sunday']. Your filter will look like:

{% for day, entriesInDay in agendaEntries | group('postDate|date('l')') %}


What other properties are in the "entry.image" object? So this may be a stupid question, but I've sort of never wrapped my head around it. When fetching an image from an entry -- even if there's only one associated with the field -- you can't just do:

{% set image = entry.image %}

You have to say:

{% set image = entry.image.first() %}

Which implies that the returned data are an object or array, and that the actual desired image is the "first" item in it. My questions are:

Why is it structured this way?
Which other properties are in the entry.image apart from the actual resource itself? What would you use those for?

I realize this may be obvious to pro Craft developers, but I remember the first Craft site I ever built, I had a devil of a time trying to remember that!

When you reference a relationship field (ie: Entries field, Assets field, etc), you will automatically get an ElementCriteriaModel to represent the "value" of that field.

Since entry.image is giving you an ElementCriteriaModel, you need to specify exactly what you want that ECM to do. If you try to use the ECM without specifying .first (or .last, or .total), then by default it will assume you meant .find. Which is obviously not what you're trying to do in this case.

I highly recommend reading my answer on this other thread... It's not quite a duplicate of your question, but it covers a lot of the same ground.


Store phonetics in plain text field I need to store phonetics for word definitions in a plain text field. An example would be something like "Craft Website" => \ ˈkraft ˈweb-ˌsīt \, like you'd see in a dictionary.

If I try saving \ ˈkraft ˈweb-ˌsīt \ in a custom plain text field, I get a database exception, presumably because it takes issue with all the unusual characters not found in UTF-8.

Does Craft have a way to handle this without needing to manually adjust my database?

Does Craft have a way to handle this without needing to manually adjust my database?

Swap to PostgreSQL? :)

This is more of a MySQL limitation/configuration issue than a Craft/PHP one.

You can alter the charset/collation of the column the plain text field is being saved to utf8_mb4 and utf8mb4_general_ci and that should solve it.


How do I print the last level of a category? Some categories have 2 levels, some only have 1 level.

How can I print the "last" level of an entry if for some it is level(2) and others it is level(1)?

I've not actually done this, but I'm guessing:

{% set category = entry.categoriesFieldHandle.last() %}

(...then .level on that to get the level if that's what you want).  .last() is the opposite of first().

(Make sure you check category|length as it might be that no categories are assigned...)


Question about "relatedTo" I want to get list of entries in my section video related to my current entry

{% for video in craft.entries.section('videos').limit('3').relatedTo({targetElement: entry.title, field: 'talents'}) %}

problem is entry.title is text, but talents is array.

The relatedTo parameter accepts an element, the ID of an element, an array if element ids or an object of type EntryQuery.

All you need to do is to pass the ID rather than the title

targetElement: entry.id

Furthermore if you use Craft 3 you might want to execute your query by calling .all()
talents doesn't contain an array. It contains an object of type EntryQuery that can be executed in order to get an array of elements


All templates automatically private Is there a way to make all templates automatically private? Or do I really have to put an _ before every single one?

Your templates will be private if they are contained in a folder prefixed with a "_"... So just make a folder like that, and put everything else inside of it:

/craft/templates/_everything/myprivatefile.html


Craft Commerce - Purchasables and multiple gateway accounts Time for my first question. "we have a client..." :)

I'd like to achieve something like:

A visitor (User A) is able to register and create a 'Team' Entry.
They then invite new users (Users B, C, D, E etc) to register by adding them to their 'Team' Entry(s)
User A then pays for the Teams they have created - I am planning on constructing a Craft Commerce 'purchasable' item for each Team Entry and passing all of the Teams to the Cart for the usual Checkout process...

Challenge 1: The client would like payments for a given city to be directed to a specific Payment Gateway i.e. Payments for the Paris Team Entries, should go to a Stripe account which the Paris office has access to and can administrate.

In a similar way, payments for London team entries, need to go via a different Stripe account which only the London office has access to.

(there will be over 13 different cities in various countries by 2017 with more added thereafter)

Q: How could I extend or override the default Stripe Account in Craft Commerce settings, based on the location of the Event which a Team is registered for? e.g. I could use Stripe API custom fields in the City Entry.

Challenge 2: Allowing a user to pay for creating Team entries - I spotted this solution by Mr Kelly from earlier this year: Using Commerce to pay for posting entry

I'd appreciate any solutions or ideas you might have - thanks in advance!

Matt

You wouldn't need to dynamically change the Stripe credentials on the Stripe payment method, rather it is more likely you would set up a seperate Stripe payment method for each Stripe account.

It is a little known feature that you can set up more than one payment method per gateway with different credentials.

You could then hard code the payment method ID to the relevant teams payment screen (or set it on the cart before they get to the payment page). You could even store the payment method ID in that teams entry.

Hope that helps for the initial question.


Redirect after saving an entry The question was already asked (Possible to redirect elsewhere after saving an entry?) but this was about Craft 2.x.

Up until now I used the following code in my plugin (I took it from one of the comments from the same question):

Craft::$app->getView()->hook('cp.entries.edit', function (array &$context) {
    if (isset ($context['section']['type']) && $context['section']['type'] === 'single')
    {
        Craft::$app->getView()->registerJs("
            $(function () {
                $('input[name=\"redirect\"]').val('/');
            });
        ");
    }
});

The code did the job, but after I updated to 3.1.32.1, it stopped working, every time after entry was saved the following exception was thrown:

  HTTP 400 – Bad Request – yii\web\BadRequestHttpException
  Request contained an invalid body param

Stacktrace:

yii\web\BadRequestHttpException: Request contained an invalid body param in .../vendor/craftcms/cms/src/web/Request.php:651
Stack trace:
#0 .../vendor/craftcms/cms/src/web/Controller.php(314): craft\web\Request->getValidatedBodyParam('redirect')
#1 .../vendor/craftcms/cms/src/controllers/EntriesController.php(595): craft\web\Controller->redirectToPostedUrl(Object(craft\elements\Entry))
#2 [internal function]: craft\controllers\EntriesController->actionSaveEntry()
#3 .../vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array(Array, Array)
#4 .../vendor/yiisoft/yii2/base/Controller.php(157): yii\base\InlineAction->runWithParams(Array)
#5 .../vendor/craftcms/cms/src/web/Controller.php(109): yii\base\Controller->runAction('save-entry', Array)
#6 .../vendor/yiisoft/yii2/base/Module.php(528): craft\web\Controller->runAction('save-entry', Array)
#7 .../vendor/craftcms/cms/src/web/Application.php(297): yii\base\Module->runAction('entries/save-en...', Array)
#8 .../vendor/craftcms/cms/src/web/Application.php(565): craft\web\Application->runAction('entries/save-en...', Array)
#9 .../vendor/craftcms/cms/src/web/Application.php(281): craft\web\Application->_processActionRequest(Object(craft\web\Request))
#10 .../vendor/yiisoft/yii2/base/Application.php(386): craft\web\Application->handleRequest(Object(craft\web\Request))
#11 .../web/index.php(21): yii\base\Application->run()
#12 {main}

Is there any chance to make it work again on 3.1.32?

The redirect url always needs to be hashed:

https://docs.craftcms.com/v3/dev/functions.html#redirectinput

In Twig you can use {{ redirectInput(url) }} which is a shortcut of

<input type="hidden" name="redirect" value="{{ url|hash }}">

But if you need the same in a PHP code you can use

Craft::$app->getSecurity()->hashData($url)

based on the code how the Twig filter defined in craftcms/cms/src/web/twig/Extension.php.


Assigning the right license to the right subdomain My client has 3 licenses, one for each of 3 subdomains. Let's call them A, B and C.
C has been derived from B, so has inherited B's license.key. How should I assign the correct license to C? Or does it not matter as long as the appropriate number of licenses have been purchased?
On a related note, my client's id.craftcms.com log stores the same root domain against all of them, so I have to put a reference to the subdomain in Notes. Not a problem as such, but the same domain for all seems  a bit imprecise.

Technically 3 separate Craft installations would require 3 separate/unique Craft licenses even if they share the same root domain (site.com) and live off in subdomains off of that (a.site.com, b.site.com, c.site.com).
If any of the sites are using the same config/license.key file, you could delete the duplicates and load the updates page in the control panel. A new one tied to Craft Solo will be generated and you can purchase Craft Pro updates for each individual site.

Not a problem as such, but the same domain for all seems a bit imprecise.

It's a bit ironic in your case because the reason we currently only track the root domain is to let all subdomains of that root domain be able to share a single config/license.key file for a single Craft installation in a multi-site setup.
Using the notes field in your Craft ID account is probably be best way to keep them sorted.


A tabbed UI for child entries wonder if a guru could help, I am nearly there, just stuck on the right call.

Building a standard css/jquery responsive tab solution. I am pulling back child entries to populate a parent page with said tabs. The problem is the for loop, not being able to close the unordered list before the next part. I wonder if anyone could help please.

{% set entries = craft.entries.section('country').level(3) %}

{% for entry in entries %}

{{entry.pageTitle}}

{{entry.pageTitle}}

{{entry.pageTitle}}

{% endfor %}

I would go for two loops to make it easier to maintain sanity later on:

{% set entries = craft.entries.section('country').level(3) %}

   {% for entry in entries %}

{{entry.pageTitle}}

   {% endif %}

   {% for entry in entries %}

{{entry.pageTitle}}

      {{entry.pageTitle}}

   {% endfor %}


Namespace issues when calling a plugin variable Making a plugin.

I can't seem to get this {% set leads = craft.lead_infopack.getPacks() %} to fire from within a template.

Plugin name: lead

Here's a look inside my variables class.

Lead_InfopackVariable.php:

class Lead_InfopackVariable
{
    public function getPacks()
    {
        return craft()->lead_infopack->leads();
    }

The leads function calls a service that outputs all entries within my 'infopack' table.

If I write it like this it works {% set leads = craft.lead.getPacks() %}

LeadVariable.php:

class LeadVariable
{
    public function getPacks()
    {
        return craft()->lead_infopack->leads();
    }
}

I think you can only have one variable class. So the solution you posted is the only way that works.


How do I output entries by their category? Ok, so basically I want to loop through categories and output the title of each category along with all the associated entries. Like so:

Category 1: Entry 1 Title, Entry 3 Title

Category 2: Entry 2 Title, Entry 4 Title

(Where entry 1 and 3 are category 1 - and entry 2 and 4 are category 2)

This was the closest I got:

    {% set categories = craft.categories.group('jobCategories').find() %}

        {% for category in categories %}

{{ category.title }}

            {% for entry in craft.entries.section('people').relatedTo(category).find() %}

                     {{ entry.title }}

            {% endfor %}

    {% endfor %}

How would I do this?

Thanks!

It might be quicker to turn it around: first get all the entries you need, then group those by their category:

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

{% for category, catEntries in entries | group('categoryFieldHandle.first().title') %}

{{ category }}

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


Filter rules as a variables I want to strip every headline tag from all Rich Text fields site-wide.

So I thought about adding a replace filter.

But since this will be site wide I wanted to write the replace rules in a variable:

{% set replaceHeadline = '"
" : "
", "
" : "
"' %}
{{ entry.richText | replace({replaceHeadline}) | raw }}

This produces the error:

  A hash key must be followed by a colon (:). Unexpected token
  "punctuation" of value "}" ("punctuation" expected with value ":").

Is this not possible? Is concatenation with ~ somehow the way to go?

Is there a more sane approach to stripping all headline tags from Rich Text fields?

You'd have to store the complete array into the variable

{% set replaceHeadline = {'
': '
', '
': '
'} %}
{{ entry.richText|replace(replaceHeadline)|raw }}

But instead of storing that variable I'd probably just create a macro for that snippet.

_includes/macros.html

{% macro formatRichText(string) %}
    {{- string|replace({
        '
': '
',
        '
': '
'
    })|raw }}
{% endmacro %}

_layout.html

{% import '_includes/macros' as macros %}

You can now use that helper macro everywhere in your templates

{{ macros.formatRichText(entry.richText) }}

Another recommendation, have a look at the RetconHTML plugin, a nice little plugin to manipulate HTML with Twig.

{{ string|retconChange('h1', 'p') }}


How should one go about using Craft with Git? [not duplicate] I've seen many other questions about Craft deployment, some of which even use Git, but none seem to thoroughly address how one would use version control on their local development environment, push changes to a remote repository, and then pull changes down to the staging or production server.

Sure, you can handle modifications to static assets and templates this way, but those changes often require modifications to sections, entries, categories, and globals, all of which are stored in the database. How would one manage the entire website through version control?

Any help is appreciated. Thanks!

Have a look at the project config feature in craft 3.1, it generates a yaml file describing all developer created data, e.g. fields, sections etc. which can be stored in GIT. However this does not save user created data e.g entries.

https://docs.craftcms.com/v3/project-config.html

Also look at migrations; php scripts to create schema / data in DB. (Which can be stored in GIT) Migration Manager plugin will auto generate them for you

https://docs.craftcms.com/v3/extend/migrations.html

https://packagist.org/packages/firstborn/migrationmanager


Force SSL on sub folder I'm having issues forcing an SSL on my website. I think the issue may be that my root folder is my 'web' folder.

I've searched online and tried a few variations of htaccess but none of them seem to work.

Here is the latest I've tried:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

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

My domain points to my web folder and my htaccess belongs in the web folder.

Thanks,

Joe

For better practice, you should never use ".htaccess" file. Especially your problem can be easily solved by modify Apache configure file.

You should be able to find an Apache configure file somewhere in your /etc folder.
On my server its /etc/httpd/conf/httpd.conf.

Then just find the code

<VirtualHost *:80>
   ... your server setting
   ServerName your-server-address.com
   # add the following line
   Redirect permanent / https://your-server-address.com/
</VirtualHost>

Don't forget to restart your server after you done the change.
This will redirect any traffic trying to visit your site with none ssl to ssl, regardless your folder structure.


Assign entries to categories in bulk? I just accidentally dragged a root category onto another. Now, all of the entries that were assigned to that category are assigned to the one I accidentally dragged it onto.

Luckily, I have like 7 entries but if this happened with a lot of them I'd be pretty screwed. It seems like a disaster waiting to happen.

Is there an easy way to "bulk assign" categories? If that's not possible is there anyway to add a "Save" button to the category manager so I'd have to click save before the database actually updates? Am I overlooking something really, really obvious here? Definitely wouldn't be the first time.

I think that, right now, the only way to deal with that is at the DB level. I believe you would only have to deal with the craft_relations table for adding / removing categories to entries.


Is it possible to add an entries field to recurring events that can be changed per occurrence? An event in Solspace Calendar that repeats weekly should have an entries field, that can be changed per single occurrence. E.g. Tuesday’s evening class is usually tought by teacher A, except next week, where it’s going to be teacher B (both teachers have an entry I’d like to link to in the event’s popover).

Is this possible?

Calendar's event recurrences are only simulated/inflated by a repeat rule for the main event. Since there is no database entry for each recurrence, there's unfortunately no way to achieve something like this at this time.


Site wide announcement banner I am looking for a plug-in that would allow me to add a site wide announcement banner to the top of a page. Much like the one in the image below:

I'm new to Craft and have gotten my site up and running but can't seem to figure out a simple way to do this.

You don't need a plugin for this task. You are free to do whatever you like in your templates. There is a template folder in your Craft directory where your html/twig files live and you are free to create the html you like.

So if you want to have a site wide banner, just include the required html in your layout template and that's basically it.

Craft is not made for non-developers so if you are going to create a site with craft you should have basic knowledge in html/css to write your layout at least.

I suggest you to read the docs or some other tutorials


Show just the first row of a table (stored in globals) Morning Craft folks, I've had a look and play but can't seem to find an answer for this.

I have a global variable with a company's various phone numbers in, stored in a table field.

The table shows the city, then the phone number for the company's numbers.

For the navigation, I want to show just the first phone number in the table.

.first() and .limit(1) don't seem to work in this situation.

    {% if companyDetails.telephoneNumbers | length %}
        {% for row in companyDetails.telephoneNumbers %}
            {{ row.number }}
        {% endfor %}
    {% endif %}

    Call us

Many thanks in advance.

first() and limit() are methods of the ElementCriteriaModel. Since a table is not an element, but just a plain array, you should use array filters.

So use Twig's slice filter instead.

    {% if companyDetails.telephoneNumbers | length %}
        {% for row in companyDetails.telephoneNumbers | slice(0, 1) %}
        {{ row.number }}
        {% endfor %}
    {% endif %}
    Call us


Session Error from Console Command I created a simplistic Console Command class in my plugin folder containing this function:

public function actionTest () {
    craft()->templates->renderString('index');
}

When I run the command:

./yiic < plugin > Test

I get the follwing error message:

Property "Craft\ConsoleApp.session" is not defined.
exception 'CException' with message 'Property "Craft\ConsoleApp.session" is not defined.' in /Users/< username >/Sites/< project >/craft/app/framework/base/CComponent.php:130

Thoughts? The end goal here is to be able to render HTML emails and them at specific intervals, but for some reason when using craft services, I get session errors.

The OP was running an older version of Craft. Resolved the issue by updating to the latest.


How to best design large queue jobs? I have a plugin that captures data and stores it as an Element, similar to a log. There can be a lot of Elements created so there is also a way to purge those Elements from the DB. In most cases, the amount of Elements being purged at a given time is reasonable. However, there are some scenarios where a user may be triggering the deleting of tens of thousands of elements.

What is the best way to handle this so that I'm least likely to crash a users site

I'm not sure what the right question to ask is so here are a few areas that a better understanding would be helpful:

Does creating a single job with 10,000 steps use more resources than creating 100 jobs with 100 steps?
If breaking things out into batches makes sense, what is a reasonable batch size for modifying Elements using a job?
Would the need to do different actions lead to a different answer? For example, would the same recommendations hold for modifying Elements and deleting Elements?

The answers to your questions will inevitably be, that it depends, however I have tried to present examples of situations that may help clarify things a bit further.

  Does creating a single job with 10,000 steps use more resources than creating 100 jobs with 100 steps?

Each queue job is stored as a row in the queue database table. If a job had 10,000 steps and needed to store a unique piece of information about each step, then the amount of data stored in the job column (a LONGBLOB) could be very large. Fetching, storing that large blob in memory and working with it would require more resources than working with smaller blobs one at a time. If part of the job execution involved fetching and working with 10,000 elements, then again that would require more resources than working with smaller collections of elements. So in theory, creating multiple, smaller jobs would take longer to complete but would be less prone to the memory and/or time limit being exceeded and the job failing.

  If breaking things out into batches makes sense, what is a reasonable batch size for modifying Elements using a job?

If you want to account for queue jobs that are run through the browser (in addition to through CLI commands) then you should try to avoid allowing a job to exceed the memory limit at all costs. However, since the memory limit can be different on every environment (Craft 3 requires at least 256MB of memory allocated to PHP) this can be difficult to do. 100 feels like a conservative batch size but again, it depends on how many resources the job requires.

What I have done in the Campaign plugin is added a block of code to each iteration in the job that checks whether the memory used by the current job (memory_get_usage(true)) and the time that has passed since it was requested (time() - $_SERVER['REQUEST_TIME']) are nearing the respective limits. If they are then I create a new job, give it a delay, add it to the queue and stop execution of the current job. That means that the SendoutJob can continue sending emails indefinitely and without a fixed limit, until it detects that the job is close to failing. Setting a delay on the new job allows the current request to end without failing and the new job will be executed the next time the queue is run. Here is the relevant code:

// If we're beyond the memory limit or time limit or max batch size has been reached
if (memory_get_usage(true) > $memoryLimit || time() - $_SERVER['REQUEST_TIME'] > $timeLimit || $count >= $batchSize) {
    // Add new job to queue with delay
    Craft::$app->getQueue()->delay($settings->batchJobDelay)->push(new self([
        'sendoutId' => $this->sendoutId,
        'title' => $this->title,
        'batch' => $this->batch + 1,
    ]));

    return;
}

Note that $memoryLimit and $timeLimit have been set to thresholds lower than that of the server (source).

  Would the need to do different actions lead to a different answer? For example, would the same recommendations hold for modifying Elements and deleting Elements?

If you decide to set a fixed limit then it would make sense that it should probably be lower for resource intensive jobs. If the completion of the job is critical then you might consider implementing a similar approach to the Campaign plugin's SendoutJob, which is not perfect but has worked well in the field.

If this is a distributed plugin then the best you can do is try to avoid jobs failing and communicate to your users what they can do to avoid it, as described in Robust queue job handling in Craft CMS.

See also: How to prevent "Failed" errors in job scheduler in Craft CMS 3?


CraftCMS 3 - Composer Update How can I update all the packages under craft/app/vendor for Craft CMS 3 (Yii 2)?

You can't.

The composer.json file (and the composer.lock file so you can't even reverse engineer composer.json) isn't shipped with the official release on purpose.

Craft 3 is still in development preview status (not even alpha release), but the next release will include updated Composer dependencies.


Update field setting value using getFieldByHandle I need to update the limit setting for Images allowed to be empty, so as to allow for no limit. How do I go about updating the 'limit' setting?

$fieldsService = Craft::$app->getFields();
$field = $fieldsService->getFieldByHandle('productImages');
// Need to update 'limit' to equal '' (currently limited to '5')
// Then save the new setting
$fieldsService->saveField($field);

SOLUTION

I was able to accomplish this by using setAttributes and setting the second argument $safeOnly to false

$field->setAttributes([
    'limit' => ''
],false);

MY SOLUTION

Use setAttributes and set the second argument $safeOnly to false

$fieldsService = Craft::$app->getFields();
$field = $fieldsService->getFieldByHandle('productImages');
// Update 'limit' value to be empty in order to accept as many images as needed
$field->setAttributes([
    'limit' => ''
],false);
$fieldsService->saveField($field);


How to handle a big amount of whitelabel sites (with multi-site) For one of our clients we need to setup a whitelabel template.
I was considering doing this with Craft's Multi site feature which works fine in that way Content management wise.

But, it's probably going to be 50+ whitelabel sites (multi sites) but, I'm afraid this is going to be a mess in the CMS.

Is there another way to handle this issue or, is this the way to go?

Craft just isn't set up to handle this many sites, as you said it will likely be a hot mess. One way to circumvent could be to create your own plugin to manage things.

Either way I would get in touch with P+T as depending on your use (if every site is a new client) this may be outside of the license agreement.


How do translations work in Craft 3? I currently have a Craft 2 site deployment with a translations folder and a en_gb.php translations file.

I would be able to use expressions like this: {{"visualization"|t}}

However, this does not work in Craft 3. What is the new format for translation in Craft 3?

You can see the changes made to static translations in Craft 3 in the Craft 3 upgrade docs here:

https://docs.craftcms.com/v3/changes-in-craft-3.html#static-translation-files

In your case, craft/translations/en_gb.php would need to change to craft/translations/en-GB/site.php.


Freeform - using multiple fields on the same form I have a set of very long forms.  Many of these forms require repetitive field types - example:  one of my forms requires the "date" field 15 times.

Another form requires at least 30 single line text entries + dozens of radio button entries.

It appears I can only use a field once per form, forcing me to create a new field each time I use a previous one.  Is there any way around this?

I see I can re-label fields for each form which helps but wondering if there is a better way.

I'm definitely going to run up against the 130 field limit if I have to create new ones each time.

No there isn't. In the same way as Craft, each field has a unique handle which is used both for templating and for email notifications.

Solspace support might have some other ideas, but I think this is just the way Freeform is built.


How can I prevent an account activation email from being sent to an unverified user who registered via a front end registration form? I have a front end user registration form, and I want users to receive a set password email after they've been activated manually in the back end by an admin. When they submit the user registration form, their account shouldn't be automatically activated, so I've checked the "verify email addresses" option in the user settings. However, with this setting enabled, a new user automatically receives an email to activate their account. Is there a way to prevent this account activation email from being sent when the user is first created in the system?

If I can prevent the initial account activation email from being sent, I can add a trigger to a custom module that sends the set password email after the user is activated by an admin, like so:

    Event::on(
        Users::class,
        Users::EVENT_AFTER_ACTIVATE_USER,
        function (Event $event) {
            $users = Craft::$app->getUsers();
            $users->sendActivationEmail($event->user);
        }
    );

This would allow me to have the set password email sent at the appropriate time.

In short, how can I have a front end registered user receive a set password email only after their account has been activated manually by an admin?

After a little more work, I came up with this approach that works-

First, I unchecked the verify email addresses option in the user settings.

Then, I added another trigger in my custom module- on before user save- that sets the new user's status to pending. The two triggers combined produce the functionality I'm looking for:

    Event::on(
        User::class,
        User::EVENT_BEFORE_SAVE,
        function (Event $event) {
            if($event->isNew) {
                $event->sender->pending = true;
            }
        }
    );

    Event::on(
        Users::class,
        Users::EVENT_AFTER_ACTIVATE_USER,
        function (Event $event) {
            $users = Craft::$app->getUsers();
            $users->sendActivationEmail($event->user);
        }
    );


Can I add a custom canonical URL to a page if also using SEOmatic? SEOmatic puts a canonical on every page. But some pages I need to be able to add a custom canonical, but not sure how to overide SEOmatic's otherwise there will be two.

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

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

{% hook 'seomaticRender' %}


Large, Complex Navigation For a while I've been having difficulty handling large navigation in craft. I built this site a while ago, and if I am honest I would probably change the structure if I was doing it again, but that's for another time.

The nav is stored in a structure and each navigation entry is either linked to an entry or a custom url is entered. There are approximately 300 pages in the entire nav.

Here is the code I use to generate the nav:

{% macro navigation(pages, id='') %}

        {% nav node in pages %}
            {% set url          = node.url|length ? node.url : node.linkedEntry|length ? node.linkedEntry.first().url : node.customUrl %}
            {% set active       = node.slug == craft.request.getSegment(node.level) %}
            {% set class        = node.children|length ? "has-children" %}
            {% set class        = active ? class ~ " active" : url == craft.request.url ? class ~ " active" : class %}
            {% set separator    = node.separator  ? 'separator' %}

                   {{ node.title }}

                {% ifchildren %}

                        {% children %}

               {% endifchildren %}

        {% endnav %}

{% endmacro %}

The problem I have is that this is incredibly slow, in some cases I see load times of over 10s, which is unacceptable! I know that this is caused by the nav and not the rest of the page content.

I use caching to speed rendering up, and this works fine, but that only really masks the problem.

I reckon that the bulk of the time is taken up checking whether it is active, what class it has etc. Is it possible to store it as a blob and run some kind of regex match on it as a whole?

I'd prefer it if the user could change the nav through the CMS, but if I am honest, this is not a necessity. I've even thought about hardcoding it!

Any one have any pointers or experience in the past?

It's those two lines that trigger database queries

{% set url = node.url|length ? node.url : node.linkedEntry|length ? node.linkedEntry.first().url : node.customUrl %}
{% set class = node.children|length ? "has-children" %}

The first one can be optimized by using the first method in the ternary condition. You just need to know if there is a linked entry, not how many. node.linkedEntry|length queries for all matching entry models and is slower than
just calling node.linkedEntry.first(). So change it to

{% set url = node.url|length ? node.url : node.linkedEntry.first() ? node.linkedEntry.first().url : node.customUrl %}

Same applies to the node.children criteria model in the second line. Change it accordingly

{% set class = node.children.first() ? "has-children" %}

That's about all you can do to optimize the code, now you should definitly add caching to it. It's not as straightforward to implement in this situation, as there's the dynamic "active" class you want to add to the output. So you have to either cache the whole navigation for each page it's used individually (each with the active class at the right place) or you use the string replacement technique described in this SE to cache the navigation globally for all pages.


Does Craft CMS have skeletons/starter/boilerplate templates? I'd like to set-up quickly blog on Craft CMS and I wonder if there are any starter templates available? It would be really useful.

Here's an example of how you can do it with Craft 3 and composer create-project: nystudio107/craft

This is discussed in the Setting up a New Craft CMS 3 Project article.


Display & check-for User Group on public profile This two-part question is half an exact duplicate of How do you display a user's User Group? but I'm unable to leave a comment :(

I'm trying to display & check-for the user group a user belongs to on a public profile page. There are coaches and players.

The URL structure is domain.com/coaches/johnnyappleseed

Copying the exact example code given in the original question (link above) seems to just return the User's full name, not the group the user belongs to. What could I be missing?

Also, if johnnyapplseed is a coach, I can still access his profile page by going to domain.com/players/johnnyappleseed which is why I'm trying to check for the usergroup to begin with. Is checking for the usergroup in each player & coach profile template the correct way to do this?

UPDATE: I've attached a screenshot of all the information I think could possibly be relevant. This has to be something simple I'm overlooking!

If you know the user will only belong to one group, something like this should do it.

{% set user = craft.users.username(craft.request.getSegment(2)).first() %}

{# make sure we found a user %}
{% if user|length %}
    {% set groups = user.getGroups() %}

    {# make sure they belong to at least one group #}
    {% if groups|length %}
        {# display the name of the first group #}
        {{ groups[0].name }}
    {% endif %}
{% endif %}


Looping through rows in a Super Table Very new to Craft & Twig. So I get the following error: Impossible to invoke a method ("url") on a integer variable ("0") with the below code:
{% if module.type == "rotator" %}

        {% for row in module.contents %}
            {% set position = loop.index0 %}
            {% set previous = loop.index -1 %}
            {% set next = loop.index + 1 %}

                     ‹

                    {{ previous.slideTitle }}

{{row.slideTitle}}

                        {{row.slideCaption}}

                    {{ next.slideTitle }}

                     ›

        {% endfor %}

{% endif %}

So basically I need a 'previous' and 'next' variable that corresponds to the previous row and the next row in the Super Table. Essentially I need a way to call the current row in the Super Table I'm at, and the previous row and next row relative to the row I'm on.
Here's what my set up looks like:

I've tried loop.index0 + 1 and loop.index + 1. But neither work and I know I am calling them in the wrong way.

loop.index and loop.index0 will both return integers.

So when you do {% set previous = loop.index - 1 %}, on the first iteratin of that loop, loop.index returns 1, then you subtract 1 from it and previous is now equal to 0.

Later you call previous.url(), which is equal to 0.url() and the error message you get says there is no method named url() for the integer 0.

If you want to access the previous row, then you can probably do something like {% set previousRow = module.contents[previous] %}.


Split posts by days similar to Product hunt I've been looking around at numerous posts but can't seem to find a solution that works without constant work arounds. I'm looking to show posts split by days they were posted similar to www.producthunt.com

Today, Yesterday -> Sunday. Then displaying the date posted e.g. 31st March from then on.

Different to most questions as this is showing live posts set out by different worded days instead of numerical. I can't seem to find a way of doing this without repeating the same code block for 7 days then a generic by date loop?

Is this possible in Craft?

This seems like a good use case for Craft's group filter. I'd recommend reading this page to get a better understanding of how it's used.

Not quite sure what your code looks like but I'll pull this from the above mentioned support article for explanation purposes:

{% set allEntries = craft.entries.section('blog').limit(null) %}

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

{{ month }}

        {% for entry in entries %}

{{ entry.getLink() }}

        {% endfor %}

{% endfor %}

So obviously you'd need to adapt this code to your setup, for example, switch out the month grouping for a per-day grouping. Then what I would do is wrap it in a conditional that only works if the postDate is more than three days older than today's date. Then you could use a similar query as the above to display the first three sections individually, (i.e. one for "Today", one for "Yesterday", and one for the day of the week of the third day).

Might not be the best way (curious to see any other answers that might show up), but just the first thought that came to mind from a quick perusal of your question.


Not seeing the entries in control panel We recently moved the site from one domain to another domain (development to staging). I am able to login to control panel and see the fields and sections but when I go to entries, i dont see any entry in there. Any help is appreciated.

Do you have multiple language set? If yes, check that you're selecting the right language on the entries drop-down.


Change Craft 3 password algorithm Is there a way to specify in Craft 3 which hashing algorithm should passwords use?
I know craft 3 uses PHP's password_hash() function, my question is: is there a way of modifying the 2nd and 3rd parameter of that function via a craft config.

I'm trying to find a way of doing this without using a separate/custom column in the users table.

Thank you.

The 3rd parameter for the hash cost you can control via the blowfishHashCost config setting.

The 2nd parameter (for the algorithm) is a bit more difficult because it's not exposed via a config setting. I assume you want to use PASSWORD_ARGON2I since that and PASSWORD_BCRYPT
 (the default) are the only two options: https://secure.php.net/manual/en/function.password-hash.php

You'd need to create a custom Application Config component that overrode Craft's security component with your own Security class.  Your own class could extend Craft's an overwrite just the hashPassword method, or any others that you might need to.


An unknown error occurred all the time When creating, editing or deleting anything in CP the notification with "An unknown error occurred" is appended at the top.

I check the console and I get a 500 on these:

/index.php/admin/actions/tasks/runPendingTasks
/index.php/admin/actions/tasks/getRunningTaskInfo

Nothing is in the logs that I can see.

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

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

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

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

Craft 3
PHP 7.2


Empty cart should remove coupon discounts in commerce Is there anyway to remove all the discounts if cart becomes empty?

I think this one is debatable from a functional perspective.
On first glance, it feels like if a cart is emptied then the coupon should be removed, but on the flip side, if they are simply changing their order and the cart is emptied along the way during that process, why should they have to re-enter the coupon?  The coupon itself is still valid, so if they have entered it, and then the cart later becomes valid for that coupon, why should it not then automatically re-apply?
I believe the only way to clear the coupon code as you wish would be to detect if the cart is empty (i.e. has no lineitems) and then post (e.g. by ajax) to update-cart an empty coupon code...something like:
<form method="POST" id="remove-coupon">
    {{ csrfInput() }}
    {{ redirectInput('/cart') }}
    <input type="hidden" name="action" value="commerce/cart/update-cart">
    <input type="hidden" name="couponCode" value="">
    ...etc


ActiveRecord Primary Key - Auto increment With Craft Active Record, using the definedAttributes Method how do I set my Primary Key Field to auto increment?

Or does it just calculate another number for the field that has not been used when the record gets saved?

Thanks for your help.

You don't need to define an id attribute in your Craft Records Class - it is created automatically for you on plugin install as an auto-incremented int. You do need to define the id attribute on the equivalent Model though, and AttributeType::Number is fine for that.


Output the contents of an instructions field within a Matrix block As the title suggests, i'm trying to output the contents of a default instructions field within a Matrix block.  I'm sure it's doable but not sure where to start?

Thanks

Martin

I just searched this Stack Exchange and found an answer on how to get the field model from the templates: How can I output the Field Name in my template?

  You can get any field with craft.fields, which returns a FieldModel:

 {% set field = craft.fields.getFieldbyHandle('field_handle') %}
 {{ field.name }}
 {{ field.instructions }}

Unfortunatelly, however, this won't work with fields within a Martix field. The getFieldbyHandle method is written for use in specific parts of the CP, where Craft knows the context the field is used in.

There's a getFieldbyId method though, which could work for your use case. The field's ID is independent from the context (inside Matrix or not).


List Categories by 0-9 and A-Z I'm trying to output a list of Brand names grouped by first letter. But some items have a number or symbol in the name. I want to list first the Numbers and symbols under 0-9 and the rest of the brands under A-Z

Like this:

0-9

+People
10 Days
2Two
40 Weft
55 DSL
81hours

A

Acne
Adidas

B

B.Young
etc etc.

To group by the first letter you would simply use the slice filter within Craft's group
filter.

For all non letter characters you can now use Craft's replace filter (it does regex since Craft 2.2)
and replace them with whatever you want these entries to be sorted by.

{% set entriesGrouped = entries|group('title|slice(0, 1)|upper|replace("/[^A-Z]/", "0-9")') %}

{% for letter, entriesInGroup in entriesGrouped %}
    {{ letter }}
    {% for entry in entriesInGroup %}
        {{ entry.title }}
    {% endfor %}
{% endfor %}


How to generate a preview URL in Twig I have a template intended for administrators (separate from the Craft control panel) where I'd like to generate tokenized preview links for unpublished posts (the same URL you get when you click on the "View" button from an entry page within the control panel). These links are intended for administrators to share with third parties so they can preview a page before it's published. Here's the Twig I have so far (which isn't working):
Preview

What am I missing?

I figured this out:
{% set token = craft.app.tokens.createToken(["preview/preview", {"elementType": "craft\\elements\\Entry", "sourceId": 123, "siteId": 1}]) %}
Preview

Make sure sourceId and siteId are set correctly.


Can't update from v2.6.2789 via manual update I can't seem to update my local dev site Craft version (2.6.2789) to the latest 2.6.2964. I've followed the steps to update manually but it has no effect and still shows the v2.6.2789 in the footer.

Is there anything I can do to update?

Are you 100% sure you are updating the right website/folder and not looking at the wrong one? Are you sure you are using the newest version of craft to install and not your old download?

If this is not the case. You could save your templates folder, All the folders you made yourself in the public folder and the plugins folder if you have any installed and make a backup of your current database and install a new fresh version of craft.

Then implement your saved files / database. Your database should be imported via the program or client you made your database in as this is not possible yet to do via the Craft admin panel. This is basically the same as a manual update.


How to configure the system messages  url? we have got a multisite environment and have imported users with different preferred languages (de and en). Therefore we made a module, cause the feedme plugin doens't set the preferred language https://github.com/craftcms/feed-me/issues/612. All the users are set to pending. Now we want to sent the activation mails for alle these imported users, so they can set their passwords.
The email is translated cause of the preferred language - thumbs up - but the  with the activation code is just from one domain - in our case the .de domain. This means, all users with a preferred language set to "en" are getting a well translated mail, with a link to the .de page and not the .com for setting their passwords.
So the question is: why is the link not dependent on the preferred language as well or could be localized via a config for this case?

This issue was discussed a while ago here: https://github.com/craftcms/cms/issues/3029
As Brandon says, Craft basically has no knowledge of which site a user belongs to as they're all global.
Bear in mind that emails that are triggered from the front end will use the domain name where they were triggered from - this problem only really affects emails triggered from the control panel.
The workaround discussed at the bottom there is probably your best bet: use Twig's replace filter to dynamically replace the domain name in the link variable according to what you know about the user (in your case, their preferred language).
{% set link = user.preferredLanguage == 'en' ? link|replace('https://www.site.de','https://www.site.com') : link %}


GIF Animations NOT Appearing I having a problem when trying to upload gif animations. It seems that the animation element doesn't work after they have been uploaded.

I looked at the Craft changelog and it mentioned something about support for gifs through ImageMagick. The site is on MediaTemple so when I used their ImageMagick install instructions it throws up an error.

  Internal Server Error

  curl_setopt() [function.curl-setopt]: CURLOPT_FOLLOWLOCATION cannot be activated when safe_mode is enabled or an open_basedir is set

I'm not sure if it is an ImageMagick thing or not but it is crucial to the function of the site. Its probably very simple.

Please help...

Thanks

You're correct in that animated GIFs will only have their animations preserved if your server has Imagick installed.

If you're getting an error installing Imagick on MediaTemple, the you're better off contacting them with the error and seeing if they can help resolve the issue.


Where do I put code to use hooks and events from Squarebit's 'Charge' plugin? I would like to update a specific entry upon the completion of a successful payment through the charge plugin. For this, Charge provides the callback 'charge.onCharge,' as detailed in the 'Hooks & Events Page' of the documentation.

The issue is that I have no idea where to put PHP code to utilize this callback, nor what this code would look like. Is there an example that would explain exactly how to use the callback, and exactly where the code would go?

You'd listen to Charge's onCharge event just like you'd listen to any of Craft's own events, using a plugin.

Your plugin's init() method, for example could do this:

craft()->on('charge.onCharge', function(Event $event) {
    // ...
});

There's a nifty Craft plugin scaffold generator to get you started here, too.


How to output the matrix block type name in Craft? Possible feature request Is it possible to output the block type name in Craft for each matrix block in your field?

Currently Craft just lists the name of each field within the block, but we are using generic field names (Width, depth etc), so in those instances there is no clear context for which block type is being used.

See the attached screenshot to see what I mean. I have just shown the 'Footprint' block type, but with the list of generic fields there is no way of clearly seeing this is actually 'Footprint', which can make things difficult for our client when they are managing content.

The second screenshot shows what I am trying to achieve, so it simply adds "Type: Footprint" to the start of the field list. Thanks!

The guys at Supercool have developed a Craft plugin that does exactly what I was after, and as a bonus it allows you to group matrix block types which is very handy.

UPDATE

As of Craft 2.3, matrix block titles are now shown as part of the core functionality, thanks P&T!