Entries field templating only when entry is added I have a section type Structure called How to videos, in which I have field type Entries.
Now, when I select "Products" in the field type 'Entries'. I only want the selected Entries Products to show text "Click here to view". If there is no entry added in entries fields it should not show text "Click here to view".
How can I template the Entries field?

You'll need to do something like this. entry is a How to videos entry.
{% set relatedProducts = entry.productsEntryField.all() %}

{% if relatedProducts|length %}
    {% for product in relatedProducts %}
        Click here to view
    {% endfor %}
{% endif %}

The Craft docs on Entries Fields has more info.


Trim trailing spaces before each new line in a multi-line string I have a string from a multi-line plain text field and I'd like to trim any trailing spaces before new lines.

With plain regex I would use this expression: /\s*$/gm

Using

{{ string|replace('/\\s*$/', '') }}

will trim out the last trailing space of the string (same as the trim filter would), but not before every new line.

I have tried

{{ string|replace('/\\s*$/gm', '') }}

and

{{ string|replace('/\\s*$/m', '') }}

but that doesn't have any effect.

How can I apply the m modifier to the replace filter?

Currently it’s not possible to pass regex modifiers to the |replace filter. You’d have to just do this manually:

{% set str = "foo     \nbar    " %}
{% set trimmed = "" %}

{% for line in str|split("\n") %}
    {% set trimmed = trimmed ~ (trimmed ? "\n") ~ line|replace('/\\s*$/', '') %}
{% endfor %}

UPDATE

As of Craft 2.5, the |replace filter supports regex modifiers.


Plugin settings per site / locale (Craft 3) This is a followup question to this question which asked about the possibility of per-site plugin config for Craft 3.

I'm a plugin author and have had a feature request for allowing my plugin to have different settings based on the current site. Looking at the above question, it sounds like this used to be possible in Craft 2:

<?php

return [
    'flagName' => [
        'de' => 'Bundesflagge',
        'fr' => 'Tricolore',
    ],
];

This doesn't work in Craft 3, alas (throws an error). I could write something into my plugin's admin area to loop through known sites and output config per-site but this seems like something Craft should be able to do out-of-the-box (especially given the above method used to be valid). Does anyone know if there's a good way to do this in Craft 3?

There is no native support for this, you can follow my approach and create a custom table for it to store the settings for each site

Another way is to return a different array depending on the current site in your config file

if(Craft::$app->getSites()->getCurrentSite()->handle === X){
    return ['flagName' => 'Tricolore'];
} else {
    return ['flagName' => 'Bundesflagge'];
}

or

$array = [
    'de' => [
        'flagName' => 'Bundesflagge'
    ],
    'fr' => [
        'flagName' => 'Tricolore'
    ]
];

return $array[Craft::$app->getSites()->getCurrentSite()->handle];


How can I break up a product into two page templates? I have a product overview page, with images and some text, then a call to action that launches a product customiser for that particular product. (the customiser is requiring some bespoke JSON using line items).
It is on the product customise page that the 'add to cart' button is placed.

I would like the following URLS for each seperate page:

Product overview:

myshop.com/products/productname

Product customiser:

myshop.com/products/productname/customise/

How would I go about doing this? By default, Craft only seems to let me use one template per product.

Any help greatly appreciated :)

I think you just need to create a dynamic route to either ignore customise/ in the url or serve up a different template altogether.

See my answer on this ticket for more information. Secondary Template for Structure


Applying an image transform returns a 404 cpresources URL EDIT 3: Started using imager and no longer have the problem. It's not a real answer to the problem but solves the problem.

This is the situation that has me pulling my hairs... I've looked at other related Q&A's but can't seem to distill a solution for the issue I'm facing.

I'm trying to apply an image transform but I get a link like /cpresources/404?x=TBKkjeyyP returned. Also, no image is being generated.

Files can be uploaded trough the backend just fine, can be linked to an entry and can be shown without applying the transform.

Any pointers as to what is going wrong? I'll gladly provide additional information if/when needed.

My setup is as follows:

Using Craft CMS 2.6.2986 on apache
3 locales configured (nl, en, fr)
local storage (File System Path: uploads/& url:  {baseUrl}uploads/)
relevant config below (using process described here)

General config:

// All environments
'*' => array(
    'omitScriptNameInUrls' => true,
    'overridePhpSessionLocation' => true,
    'usePathInfo' => true,
    'cacheDuration' => false,
    'useEmailAsUsername' => true,
    'generateTransformsBeforePageLoad' => true,
    'siteUrl' => array(
        'nl' => getenv('CRAFTENV_SITE_URL').'nl/',
        'fr' => getenv('CRAFTENV_SITE_URL').'fr/',
        'en' => getenv('CRAFTENV_SITE_URL').'en/',
    ),
    'craftEnv' => CRAFT_ENVIRONMENT,
    'environmentVariables' => array(
        'baseUrl'  => getenv('CRAFTENV_BASE_URL'),
        'basePath' => getenv('CRAFTENV_BASE_PATH'),
    ),
    // development environment
    'development'  => array(
        'devMode' => true,
        'enableTemplateCaching' => false,
        'allowAutoUpdates' => true,
    );
);

Relevant CRAFT_ENV settings:

'SITE_URL' => $protocol . $_SERVER['HTTP_HOST'] . '/',

'BASE_URL' => $protocol . $_SERVER['HTTP_HOST'] . '/',

'BASE_PATH' => realpath(dirname(__FILE__)) . '/www/',

EDIT: Part of the code applying the transform:

{% set thumb = blog.previewImage.first() %}
{% if thumb %}
    <img src="{{ thumb.getUrl("blogPreview") }}" width="{{ thumb.getWidth("blogPreview") }}" height="{{ thumb.getHeight("blogPreview") }}">
{% endif %}

EDIT 2: relevant log entries

  Level warning
  Category    application
  Message [Forced] Image “gasmeters.png” could not be found.

  Level trace
  Category    system.db.CDbCommand
  Message Executing SQL: DELETE FROM craft_assettransformindex WHERE id = :id. Bound with :id='70'

For what it's worth, I also had his issue, turned to imager, which gave me some more useful error messages as to my root cause of the issue:

You may need to make sure that the path to the asset file is complete, not just relative to the site base. So for instance, a base path of ./assets works fine for standard purposes, but appears no use for transforming images, you would need http://site/assets.

If your setting a base path in config, you can use something like

'environmentVariables' => array(
    'assetsBaseUrl' => '/assets',
    'assetsBasePath' => "{$_SERVER['DOCUMENT_ROOT']}/assets",
),


"Unknown package has no name defined" composer error on upgrade Upgrading from Craft 3.4.20 running Composer 1.10.17 on PHP 7.2. Running ./craft update all returns the following error:
error: Unknown package has no name defined. [followed by JSON object related to GuzzleHTTP]

The error appears to be related to GuzzleHTTP. For testing I did the following:

Deleted the /vendor directory.
Deleted the composer.lock file.
Removed all composer.json dependencies except craftcms/cms, vlucas/phpdotenv and ext-json.
Ran composer install.
Ran ./craft update all.

Yielded same error.
Unfortunately, I am unable to find any information about this error from Composer documentation or bug reports.

Very similar to Devin's answer.
I came up against this on Friday and I had to follow these steps to resolve this issue.

Nuke the vendor folder within the project. rm -rf vendor/
Nuke the composer.lock file within the project. rm composer.lock
Clear the composer cache composer clearcache within the project.
Rollback to composer v1 composer self-update --1
Update composer globally to smooth it out composer global update
Then reinstall composer install within the project.
Finally, I was able to run ./craft update all

Hope this helps anyone else who comes up against this. It took several hours to resolve and figure out the necessary steps.


Is 'real crop' a possibility? Ok, this is the first time I need this, but here's my question:

If crop is selected for a transition, what you get is a scaleAndCrop. Is there a way to do a 'real' crop, so no resizing before cropping?

Currently, no.

It is on our list to open us the asset transformation pipeline so that plugins can add new transforms that go beyond what is available out of the box in Craft, though.


asset.getUrl() not correct: missing subfolder directory I created a new asset source/folder called "my-assets".

It has an entry in the DB in "craft_assetsources" with the id=10, path="my_base_folder/assets/my-assets/" and url="/assets/my-assets/",

plus an entry in the "craft_assetfolders" with the id=27, sourceID=10 and name="my-assets".

Then I've created a subfolder called "my-images", which only has an entry in "craft_assetfolders" with id=28, sourceID=10 and path="my-images/".

When I use the myImage.asset.getUrl() on an image from that subfolder, I get the url "/assets/my-assets/myImage.jpg" instead of "/assets/my-assets/my-images/myImage.jpg", which obviously results in the image not being found.

Any ideas why this happens and especially how to fix it?

I appreciate any help!

Go to setting, then try to click Update Assets Indexes.


How can I set my upload path by date? I have a directory structure in place that I'd like to mimic in Craft. File uploads are first categorised by Year, then by month so the directory sturcture is like such

-- 2014
---- 01
---- 02
---- 03
---- 04
---- 05
---- 06

I've tried this but it still only uploads to the root folder I setup in sources

/uploads/{postDate.format('Y')}/{postDate.format('M')}

Am I using the wrong syntax? Do I need to use now | date ('Y') instead?

First you create an asset source uploads. Then you create an asset field and set its upload location subfolder to {postDate|date('Y')}/{postDate|date('m')}

When you edit an entry, any files you upload will go in the subfolder for the year and date. If you have selected Restrict uploads to a single folder? in the asset field, then only assets in that subfolder can be used.


Max character limit on WYSIWYG text editor plugin? Is it possible to add a max character limit to CKEditor, Redactor, or any other rich text, or WYSIWYG plugin??

I've searched around, and I'm surprised that I have not been able to find a solution. Seems like a pretty basic feature. I would like to not have to use a third-party plugin for this one thing. But if that's the only way to do it, please indicate that. Thank you!

It works for me, just changing the config file:
{
  "buttons": ["html", "bold", "italic"],
  "plugins": ["fullscreen", "**limiter**", "counter"],
  "linkNewTab": true,
  "toolbarFixed": true,
  **"limiter": 235**
}


Console script tags garbling up non-html output (e.g. json) when in devMode I have a plugin returning json from a controller action using $this->returnJson(...).

Works great in production, but when devMode = true, the json is invalidated because Craft is still dumping the console debugging script at the end of the content.

What's the best way to avoid this?

Just remove these two logging routes from your plugin's init() method in your PluginHandlePlugin.php file:

craft()->log->removeRoute('WebLogRoute');
craft()->log->removeRoute('ProfileLogRoute');

That will prevent the extra logging and profiling information to be output in the browser's console when devMode is enabled.


Craft Commerce: Sort Products By Price Trying to sort products by price.

Since the price of a product in Commerce isn't a textual custom field it's attached to a variant, I'm having trouble working out the syntax to make this happen.

{% set products = craft.commerce.products({
     relatedTo: (category),
     order: defaultPrice,
}) %}

This seems close but delivers "Variable "defaultPrice" does not exist"

Appreciate any direction.

Close!  This should do it:

{% set products = craft.commerce.products({
    relatedTo: (category),
    order: 'defaultPrice',
}) %}

With the quotes it's a string.  Without the quotes, Twig is expecting a variable you've defined called defaultPrice that doesn't exist.


Generating pending image transforms stuck in process In the CMS the progress indicator for tasks is stuck and not completing its jobs. What can I do to resolve this?

More of a "How do I debug stuck tasks" answer, but it should help you.

Open up your craft_tasks table. You'll see one task in with a 'status' of 'running' and if you refresh the table several times, the 'currentStep' value for that task is no longer incrementing.  That's your stuck task.

Set that task's status to 'pending', and reload any page in the control panel to re-trigger the task.

If it gets stuck again, immediately go to your craft/storage/runtime/logs folder and check for a phperrors.log file.  If that exists, it will likely hold the error message for why the task is hung.

90% of the time, when a task gets stuck, it's because it has ran into some environmental limitation (PHP max_execution_time, memory_limit, etc.).

Update:

Just added a help article for this here: https://craftcms.com/support/stuck-tasks


Setting query offset I need to batch process a set of data. To do this I am using the code below. I am trying to process 100 at a time, but the offset doesn't seem to work. It works the first time, but in the second iteration of the loop it doesn't set the offset properly.

  $criteria = craft()->elements->getCriteria(ElementType::Entry);
  $criteria->section = 'affiliates';
  $criteria->limit = null;
  $row_count = 6000;
  $batch_size = 100;
  $num_batches = ceil($row_count / $batch_size);
  $offset = 100;

  for ($j=0; $j <= $num_batches; $j++) {
      $query->setOffset($offset);
      $query->limit = $batch_size;
      $offset = $offset + $batch_size;
      $queryResults = $query->queryAll();
      $affiliates = EntryModel::populateModels($queryResults);

      foreach ($affiliates as $affiliate) {
        //process
      }
   }

Not totally sure I understand everything going on in your example code, but I believe it could be a simplified a little:

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'affiliates';
$criteria->limit = null;

$rowCount = $criteria->total();
$batchSize = 100;
$numBatches = ceil($rowCount / $batchSize);

$criteria->limit = $batchSize;

for ($i = 0; $i < $numBatches; ++$i) {
    $criteria->offset = $batchSize * $i;
    $affiliates = $criteria->find();
    foreach ($affiliates as $affiliate) {
        //process
    }
}

Tested, and works.


Commerce Bundle Product I have a client who needs to list product "Bundles" as individual products. So basically, there would be products x, y, and z, all with their own SKU, and then bundle A with it's own SKU. Bundle A is all three products (x, y, z) at a discounted price. When Bundle A is purchased, the SKU is sent to their ops and packaging team (we have an integration from Commerce to their warehouse software).

The thing is, only bundle A's SKU is sent on purchase, which is fine because the warehouse team know what products belong to what bundle. However, the products in the bundle (x, y, z) have variations.

Is their some reasonable to add a product connection field to the variation of the Bundle? The issue is that the Bundle SKU would need to stay the same, but the customer needs to able to pick the variations of the related products that are in the bundle and have it stored in Commerce for the warehouse team to manually check. I'm a little lost on how to handle this. Basically, when a bundle A is ordered, their needs to be some way to store what variations of the related products were chosen for the bundle. Any suggestions, or am I missing some basic feature that would cover this?

Edit

Due to the rush of this job (customer wants this for the shopping season) I'm thinking this (thoughts or comments asked for):

Make a Variation text field (bundleChoices) for the bundle. On the bundle add-to-cart page where all products in the bundle are listed, use Javascript to stop the add-to-cart button, collect the bundle's product's variation choices and skus, and fill in a hidden (bundleChoices) field. Then add the bundle product with plaintext data describing the product variations chosen for this bundle.

Edit

We've decided to drop product variants in a bundle product. So if you buy a bundle, you get product x variant a, product y variant f, and product z variant q, no substitutions on the products normal options. To accomplish this, a bundle product will have a field for SKUs where just copy and paste the variant SKUs you want attached to the bundle.

Without thinking about it too deeply, I think rather than sending the single bundle Id, you will probably want to use MultiAdd for this - https://github.com/verbb/multi-add - and basically set up a form that intercepts the user choices and translates those to the appropriate variant Ids for submission to Commerce.


How do I show entries that do not have a certain category? I’m aware of the relatedTo() parameter for entries that belong to a category but how can I show entries that are NOT relatedTo() a certain category?

I found this to work, although maybe there’s a better method.

{% set excludedCategory = craft.categories.id('100') %}
{% set excludedEntries = craft.entries.section('blog').status('live').relatedTo(excludedCategory).ids() %}

{% set entryIds = craft.entries.section('blog').status('live').ids() | without(excludedEntries) %}
{% set entries = craft.entries.section('blog').status('live').id(entryIds) %}


How do I create console commands for my module or plugin? I would like to create a custom console command for my Craft 3 plugin. I've looked at the Yii docs and understand commands are defined using controllers extending \yii\console\Controller but cannot work out how these controllers should be registered with the application.

To register site routes in Craft 3, we listen for the UrlManager::EVENT_REGISTER_SITE_URL_RULES event and then define rules. What's the equivalent for registering console commands?

Thanks

What's the equivalent for registering console commands?

You don't need to listen to an event to create a console command. Assuming your namespacing and autoloading is set up correctly, they'll "just work".

I'd suggest going over to https://pluginfactory.io/ and select with Craft 3 plugin or module and tick the "Console Commands" checkbox to see a working example of how the files and structure is set up.


Plug-In Store doesn't have the option for adding / trying plugins (post upgrade 2.6 -> 3.5) Having recently upgraded a dev instance of CraftCMS 2.6 to 3.5, I'm trying to add the plugins via the store.  I can find all the plug-ins I want to add, however there's no option on the page to add / try the plug-in.  I figure I've probably missed something basic.
Anyone got an idea of what I should be looking for here?
(am pretty new to this environment...)

If you look in your config/general.php, you will probably find that you have 'allowUpdates' => false set for the environment you are trying to trial the plugin on (stage/prod?).
Change that to 'allowUpdates' => true and you will be able to install what you want.


Entries field in categories URI Is there a way to pass value of an entries field into category URI format?

{% if object.level == 1 %}

{slug}-{entries.one().slug}

{% else %}

{slug}-{parent.uri}

{% endif %}

Thanks.

If your entries field is in the layout of your category

{% if object.level == 1 %}
    {% set entry = object.entriesFieldHandle.one() %}
    {slug}-{{ entry? entry.slug : '' }}
{% else %}
    {slug}-{parent.uri}
{% endif %}


How does the new caching works (3.5+) Just upgraded to Craft 3.5+ the pages are cached (instant load on a 2nd run) but the templatecaches and similar tables are empty. How exactly does it work now? How do I flush cache for 1 specific page since it's not possible to see the rows in db?

You can read the technical details of it here: https://github.com/craftcms/cms/issues/1507#issuecomment-633147835
Craft no longer keeps track of element queries needed for cache invalidation in the database, but they are stored in Craft's data caches Craft::$app->getCache(), which uses the file system by default and it uses more of a tag-based cache invalidation strategy (similar to https://plugins.craftcms.com/cache-flag if you've ever used that).


Add a method to an existing element Trying to get my head around plugin development. Sorry if this is a super basic question. How do you add a method to an existing element? I’m trying to get any active Commerce 2 subscriptions for a user. I figured out how to add it as a variable to my plugin.

public function getActiveSubscriptions(int $userId): array
{
    return Subscription::find()
        ->userId($userId)
        ->status(Subscription::STATUS_ACTIVE)
        ->all();
}

It’s called by {% set subscriptions = craft.myPlugin.getActiveSubscriptions(currentUser.id) %}

That works, but I feel like the “right” way is to be able to do this {% set subscriptions = currentUser.getActiveSubscriptions() %} How do I do that?

You can do that with Behaviors. There is a good Working example made by Pixel and Tonic team within their Git for the DotAll workshop

namespace ontherocks\behaviors;

use craft\elements\db\EntryQuery;
use craft\elements\Entry;
use craft\elements\User;
use yii\base\Behavior;

/**
 * Class UserBehavior
 *
 * @property User $owner
 * @property EntryQuery $recipes
 */
class UserBehavior extends Behavior
{
    public function getRecipes(): EntryQuery
    {
        if (!$this->owner->id) {
            // just return a query that is doomed to fail
            return Entry::find()
                ->id(false);
        }
        return Entry::find()
            ->section('recipes')
            ->authorId($this->owner->id);
    }
}

See how to attach behaviors

// define user behavior
Event::on(User::class, Element::EVENT_DEFINE_BEHAVIORS, function(DefineBehaviorsEvent $event) {
    $event->behaviors[$this->id] = UserBehavior::class;
});

You can attach your custom behavior to the user class as well exactly like the code above and do

{% set user = currentUser %}
{% set subscriptions = user.getActiveSubscriptions() %}

Or you attach the behavior to the SubscriptionQuery and do

{% set subscriptions = craft.subcriptions.activeSubscriptions(currentUser).all() %}


How do you unit test plugins? I have Codeception running on my local install without errors, but it's not yet actually doing anything. I am building several plugins and I can't figure out how you actually test a plugin? I have no app code at all, all functionality comes from the plugins.
I have seen other plugins running their own custom PhpUnit code inline, but shouldn't I be able to fire off Codeception from the root app and it will test available plugins?
Fully aware that this is a vague question, but I can't find any information about specifically testing Craft plugins.

Have you been through Craft's testing documentation? https://craftcms.com/docs/3.x/testing/
There's a pretty good walkthrough of the necessary steps there to test plugins: https://craftcms.com/docs/3.x/testing/testing-craft/setup.html
Or if you like more real-world examples, Commerce's tests are a good place to start: https://github.com/craftcms/commerce/blob/develop/codeception.yml
From then, you'd trigger all unit tests from the root of your project like:
./vendor/bin/codecept run unit

Or every test in a single file with:
./vendor/bin/codecept run tests/unit/helpers/LocaleHelperTest.php

Or a specific test within a single file with:
./vendor/bin/codecept run tests/unit/helpers/LocaleHelperTest.php:testEmailGetOrderLanguage


Dev mode giving multiple errors but everything works I use for example {{ craft.config.baseUrl }} where baseUrl is a custom variable in general.php

This works fine. But when I enable devMode it gives a template error 'craft variable unknown'.

I also get other template errors such as variable 'entry' unknown but I don't have a variable called entry in that template. These errors happen in my _layout template.

Weird thing is that with devMode false everything works fine.

I'm on mobile now but can post detailed code tomorrow if necessary.

One of the things Dev Mode does is put Twig into a strict mode where it will throw an error any time a variable is referenced that isn’t defined. So that explains why you’re only getting these errors when Dev Mode is enabled. The errors should also show the part of your template code where the error occurred.

If you are certain that this is a bug, please send in a ticket from your Dashboard, including your DB backup and template files, so we can look into it.


Plugin Development: intercept Entry before returned to template Is there a hook in Craft to intercept an Entry before being returned to a (front-end) template? Thinking here of ways we can manipulate what is being returned in the Element Criteria Model without affecting the underlying content.

Thoughts appreciated

Probably depends on the specifics of what you're trying to accomplish, but your best bets I'm guessing would be to listen to some of the element level events, make sure it's an entry and a site request, then do your logic.

onBeforeBuildElementsQuery, onBuildElementsQuery, and onPopulateElements are potential candidates.


Error on upload: "Impossible to create the root directory..." In Craft 3.2.10, I'm getting this error message when I try to upload an image asset:

  Upload failed. The error message was: “Impossible to create the root
  directory "/Users/me/Work/Client/repo/web/craftcms-assets/project-slide-photos". mkdir():
  Permission denied”

I've made the permissions for project-slide-photos to 777 and 774, and likewise tried both for the parent directory. Is it trying to create a directory that's already there? I tried removing project-slide-photos also, and it still doesn't work.

What do I need to do to make my assets upload into this directory?

Edit: Wondering if using Docker Compose could have something to do with this:

docker-compose.yml:

version: '3'
services:
    web:
        image: 'flipbox/php:72-apache'
        ports:
            - '80:80'
            - '443:443'

        volumes:
            - '.:/var/www/html/'
        environment:
            ENVIRONMENT: dev
            DB_SERVER: db
            DB_USER: craft
            DB_PASSWORD: craft
            DB_DATABASE: craft
            XDEBUG_ON: "yes"
            XDEBUG_HOST: "host.docker.internal"
            XDEBUG_IDEKEY: "PHPSTORM"
            APACHE_DOCUMENT_ROOT: "/var/www/html/web"
    db:
        image: 'mysql:5.7'
        restart: always
        ports:
            - '3306:3306'

        volumes:
            # Location to import a database dump.
            - ./src:/docker-entrypoint-initdb.d
            # Location of the generated mysql files.
            - ./mysql:/var/lib/mysql

        environment:
            MYSQL_ROOT_PASSWORD: password
            MYSQL_DATABASE: craft
            MYSQL_USER: craft
            MYSQL_PASSWORD: craft

I understand now within the context of you are using docker. Since docker creates a new file system separate from your computer's file system, you will want to run these commands on the docker instance.

I do not use docker regularly, but I believe you can use docker attach while the droplet is running to access the droplet's file system.

You will want to set the parent folder to have higher privileges. Try this command:

chmod 774 craftcms-assets

Privileges are composed of three numbers: self, group, and world. There are also three access levels: read, write, and execute. 7 will give access to read, write, and execute. You will want to use 7 for your own commands (self) and for craft's commands (group), but not for the general public (world).

Hope this helps!


Variable doesn't exist in one locale I have a super strange problem.

I've created three locales: de fr en

I've set up all the necessary steps for a multi language config and everything works fine.

Except in the en locale I get a Variable "xyz" does not exist.

de and fr work just fine but english does not.

The variable is a global field. If I strip my templates from all globals it's working fine.

Otherwise each and every global field throws the Variable does not exist error in the en locale. How is that even possible when the other locales work just fine?

I' cant access the en globals in the control panel. Error: url not found. I guess this is a routing problem.

If found the issue.

I didn't specify define('CRAFT_LOCALE', 'de'); in the root index.php.

It doesnt suffice to create en fr folders and specify define('CRAFT_LOCALE', 'xx'); there.


Remove/stop 'redactor-inline-converted' Not specifically a Craft problem but I'm struggling to find an answer from Redactors site.

I've got over 100 occurrences of class="redactor-inline-converted" littered throughout the markup of Rich Text fields. How can I stop Redactor adding this class?

Update 2016-04-26

Here's the steps to recreate this. It's an odd thing between Redactor and Word.

Have styled text in Word with a superscript
Copy / paste in to Craft
Add some text and format it
Check the source and Redactor will add class="redactor-inline-converted"

This happens randomly on all tags:

Superscript

list item

Video example:
http://sendvid.com/h41rosb3

Not a solution, but I strip it out as part of a cleanup macro that runs on body text.

{% macro cleanup(string) -%}
    {%- if string|length -%}
        {{- string|typogrify|replace('

','')|replace('redactor-inline-converted','')|raw -}}
    {%- endif -%}
{%- endmacro %}


Opening and closing table within a switch Within my matrix I have two blocks: Day and Event. Day is just a date field while the event block has two text fields.

What's the best way to wrap the event data, which needs to show up as a table format within this loop?

This currently spills everything out in the correct order but the table doesn't open and close correctly around the event block.

The final output should look something like

Title (h2)

Table open
TR
TR
TR
Table close

{% for block in entry.scheduleMatrix %}

{% switch block.type %}

{% case 'day' %}

{{ block.day.format('l - F j, Y') }}

{% case 'event' %}

{{ block.eventTime }}
            {{ block.eventName }}

{% endswitch %}

{% endfor %}

I think the opening and closing tags in the table are in the wrong spot. Try opening and closing the table inside the event case.

{% for block in entry.scheduleMatrix %}

{% switch block.type %}

{% case 'day' %}

{{ block.day.format('l - F j, Y') }}

{% case 'event' %}

{{ block.eventTime }}
            {{ block.eventName }}

{% endswitch %}

{% endfor %}


Is it possible to limit how many times and entry type can be used? I've structured my site so that most of the pages are in a single structure section (easier to manage that way and it means all my pages can be outputted and organised in the navigation's {% nav %} tag).

I've set up pages that have their own templates and would have been singles as new entry types (e.g. contact page, register form or members area) but it means that the user might try to add another one of those sections in, which I don't want them doing.

So is there a way to limit how many times an entry type can be used?

If you're working with frontend forms, set the permission to use any of these entry types to a specific user group or to admins only. Use isInGroup or the admin property:

{% if currentUser.admin %} ... {% endif %}
{% if currentUser.isInGroup('usersWithSomeEntryTypesHidden') %} ... {% endif %}

If you need this in the CP, you could make a plugin that does the same and hides selected entry types from the dropdown using JS. As this is no nice solution, what about making this a feature request to Pixel & Tonic?


Change message if database error Is it possible to route to a nice "Site is currently offline" error page if there is an issue connecting to the database?

Currently you'll see something like the message below which isn't very customer friendly.

An exception has been thrown during the rendering of a template ("Craft canâ€™t connect to the database with the credentials in craft/config/db.php.")

On a default Craft install if I'm logged out and hit the front-end of the site with purposefully messed up database credentials, I get a nicely styled Craft 404 page if there is no craft/templates/404.html and a front-end 404 page if there is.

I believe the issue is that you've got your own front-end 404 template that's also trying to access the database and it can't.

So basically the first error is thrown (can't access the database), then another error happens (I really can't access the database) when trying to tell you about the first error.

By this point, Yii thinks the error has already been handled, so it falls back to CApplication->displayException().  I assume in this case, some content header or encoding isn't set properly and you see the garbled ’ character.

So until/if we can think of a way to guard against this scenario, your best bet is to make sure that your 404 template isn't triggering a database call.


Dymanic 'active' class using nav tag looping through a structure My question is related to this page... How can I add a dynamic "active" CSS class to the navigation on any given page?

Thank you in advance my code is the following:

    {% nav menu in craft.entries.section('mainMenu') %}

            {{ menu.title }}

    {% endnav %}

I am using Ben's code from this page but I am struggling to get this method working. I was wondering if someone could help me get to the bottom of this. I assume menu.id does not match entry.id and therefore the class is not added but how can I check the two id's are matching?

My recommendation is to match the slugs as opposed to the ids as this is much easier to debug.

    {% nav menu in craft.entries.section('mainMenu') %}
        DEBUG: Entry.slug={{ entry.slug }}
        DEBUG: menu.slug={{ menu.slug }}

            {{ menu.title }}

    {% endnav %}

Then obviously remove the debug lines once everything is working as intended :)


PHP transformed image? I’m using Craft to add CMS functionality to an e-commerce website via craft/app/bootstrap.php

Trying to pull a 'timeline' structure with a featuredImage Asset Field.

This code works and pulls the full size image, but I can’t work out how to pull the ‘small’ size of image which is set up as a transform.

I assume it should be something like $entry->featuredImage[0]->url['small'] but nothing seems to be working.

Any help appreciated.

$timeline = Craft\craft()->elements->getCriteria(Craft\ElementType::Entry);
$timeline->section = 'timeline';
$timeline->with = 'featuredImage';
$timeline->withTransforms = 'small';

foreach ($timeline as $entry)
{
  ?>

<img src="<?php echo $entry->featuredImage[0]->url; ?>" alt="<?php echo $entry->featuredImage[0]->title; ?>"/>

<?php echo $entry->title; ?>

          <?php echo $entry->body; ?>

  <?php
}


Is it possible to use images as variant selectors when choosing products? I am fleshing out all the main parts of my commerce site and going through all the requirements needed.

I have installed the Craft Commerce plugin and set it up with required shipping, delivery, etc.

One thing I am trying to fathom and work out now is the ability to customise the variant selector. I want to use images from the fields in the product editor so you can select the variant colour/material/size as a different dropdown so we may have all three in one product.

When they are selected it would:

Change the image to the selected one
Also change price
Remember when added to cart that the selected items are the correct ones for the basket

Can this be done in Craft Commerce?

I am sure you've worked this out by now, but in general terms, how you build this is entirely up to you, in front end terms.  You can make it as fancy or as simple as you like, in terms of the UI.  From simple checkboxes to some totally flash JS based UI, it's entirely up to you, as long as the form then submits the right values.  You can display any fields you wish (including images and prices) - from both the product and the specific variant(s) you're showing.

The only thing Commerce actually cares about is the purchasableId and quantity (qty) that you pass when you POST the updateCart form.

Again, when it comes to display of the basket, you will get a lineItem with the chosen purchasableId and from there can get back to the product and all its fields easily enough.  But how you choose to actually display this is again entirely up to you - you can, for example, create a basket that allows the customer to change the variant on the fly (you'd perhaps send an ajax remove item followed by an ajax add of the newly chosen purchasableId and qty).


How can I retrieve Users of a specific User Group with GraphQL? I want all the users but filtered by User Group:

query getAllUsers {
  users {
    id,
    username
  }
}

I cannot see any query parameter on the Schema

This is not possible on Craft 3.3.x but group and groupId have been added since 3.4.0-beta.5 (commit)

With the update, you can do:

query getAllUsers{
  users(groupId:1) {
    id,
    username
  }
}

Or:

query getAllUsers{
  users(group:"groupHandle") {
    id,
    username
  }
}


Problems translating the default "Name" field on tags I'm building a multi-lingual site (english and spanish) and I have a news section with entries that have a "tags" field attached.

I've marked this field as "translatable" in the CP.

But, when I've added a tag to an entry, double clicking it reveals the pop-up field editor where I can switch between locales as expected (see screenshot). But I can't enter different values for "Name" in each locale. It behaves like a  non-translatable field where changing the value in one locale changes it for all the others.

Setting my "tags" field as translatable in the CP seems to allow me to assign different tags to the entry for each locale, but that's not what I want. What I want is to have an entry's tags persist across locales, but be translated into their appropriate language.

Is the default "Name" field for tags translatable? How should I be setting this up to get the behavior I want?

Thanks for the help.

I can confirm this is indeed the case (as of  2.1.2564). I don't know if it's intended behaviour or a bug, but I would wager the former.  I seem to recall somewhere learning that P&T made an explicit decision to not have tag Names be translatable.

As a workaround you could consider a tag custom field with a "translatable label" that you fill in for each language? Seems a bit lame. I'd probably opt for simply making the field itself translatable, and then binding separate tags for each language.


Order of {% set %} tags changing output unexpectedly I have a content builder matrix that I'm looping through to build my page. That code works with no problems.
{% set content = entry.pageBuilder.all() %}
{% for block in content %}
    {% include "blocks/_" ~ block.type ignore missing %}
{% endfor %}

Above that block, in the same template, I'm trying to create a text blurb from one particular field type within that matrix. When I try to define what field to pull the blurb from, suddenly the above code only outputs the content of the blurb field. This is the code that breaks my template:
{% set blurb = entry.pageBuilder.type('copy,faq').limit(1).all() %}

But, if I move it below the "set content..." chunk, it works as expected.
It seems like these should be two completely unrelated chunks of code, and I don't understand why the "set blurb..." code is interfering with the other code when placed above it. Am I missing something?

This is a change in behaviour from Craft 2 to Craft 3 and here is the explanation.
In short, you need to clone your query (docs), something like the below should work:
{# Initiate your query #}
{% set content = entry.pageBuilder %}

{# Clone the original query to get your blurb #}
{% set blurb = clone(content).type('copy,faq').limit(1).all() %}

{# Get everything #}
{% for block in content.all() %}
    {% include "blocks/_" ~ block.type ignore missing %}
{% endfor %}


Redirecting with http status code doesn't render template TL;DR

Is there a way to redirect with a status code and have the correct template load with the correct status code?

I have template code which looks like this:

{% if slug is defined %}
 {% set entry = craft.entries.section('foobar').slug(slug).first() %}
 {% if not entry.editable %}
    {% redirect 403 %}
 {% endif %}
{% endif %}

This works fine and redirects to the 403 template, but the problem is that is just redirects (changes the url) to /403 with a status code of 302

So I followed from this question and used the second parameter to set the status code like so:

{% redirect 403 403 %}

Which sets the status code fine but now my 403 template doesn't load. If I try it with 404 the same problem applies.

When I go to a 404 page which is handled by Craft (no redirect tag) then the status code is set correctly and my 404 template loads just fine.

Is there a way to redirect with a status code and have the correct template load with the correct status code?

{% exit 403 %} seems to be the answer! Seems so obvious now... facepalm


How to override default root URL of plugin? how can I override default root URL behavior via routes? I did following but not working:

'pluginname/' => array('action' => 'pluginName/Controller/actionName');

my template file name is index

This works for me:

public function registerCpRoutes()
{
    return array(
        'settings/plugins/pluginname/index' => 'pluginname/index'
    );
}


Error when calling methods between two services (triggered by init) I have two Services in my plugin. MyPluginService is the "main" service, and MyPlugin_OtherService accomplishes some other tasks (when it is occasionally needed).

There is an init method in MyPluginService which starts a chain of events, and under certain circumstances will call a method in MyPlugin_OtherService.

MyPluginService

public function init() {
    parent::init();
    if ("conditions are met") {
        craft()->myPlugin_otherService->methodInOtherService();
    }
}

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

MyPlugin_OtherService

public function methodInOtherService() {
    craft()->myPlugin->methodInMainService();
}

While the method in MyPlugin_OtherService is being run, it will refer back to a method in MyPluginService. This is where the error is triggered:

  Fatal error: Call to undefined method stdClass::methodInMainService()

I don't understand why it's not recognizing that call to the main service method. Hasn't the main service already been initialized before this point? There is a lot about "lazy loading" that I don't understand, maybe this falls in that knowledge gap.

Your service’s init() function gets called immediately after it is loaded – and before Yii has had a chance to remember that craft()->myPlugin should return the service instance.

Take a look at these two lines from CModule::getComponent() (the method that the magic getter invokes when you call craft()->somePluginName):

$component->init();
return $this->_components[$id]=$component;

So when MyPlugin_OtherService::methodInOtherService() tries to refer back to craft()->myPlugin, craft()->myPlugin has not yet been assigned to the service instance, which results in the PHP fatal error you’re getting.

I can propose a change that would fix this:

$this->_components[$id] = $component;
$component->init();
return $component;

…but I’m not sure what the implications would be for that.

You might just need to question whether it’s so important for this code to be running from init() as opposed to another function that you’d have to invoke manually. Having it in init() could lead to other unexpected consequences as well.


Populating Matrix Blocks with JavaScript I need to populate a matrix block field with JavaScript in the control panel. I've got the data ready, but i can't figure out how to add it.
I've located a function called addBlock() in MatrixInput.js but I can not figure out how to call it from my JS code. I've explored both the global Craft and Garnish - without finding the function. I could recreate the entire html of the element, but that seems unnecessary when there are helper functions that I could reach for.
Looks like craft is creating one var for each block available on the page with the following code:
var matrixInput = new Craft.MatrixInput("...")
var matrixInput = new Craft.MatrixInput("...")

It would also be great to have the arguments that needs to be passed to the function - is there any documentation or anyone who struggled with this previously that can point me in the right direction?

This is not documented because the P&T team sees this as internal functionality I guess.
Looks like the control panel is going to be rebuilt in version 4 anyways probably in Vue. So you would have to rewrite your entire script too. If it‘s going to be Vue there is probably no way to use their JS API anyways.
Even if it sounds funky I would suggest you to imitate the user input with JS. Just crawl the DOM for the buttons and inputs and fire click and input events on these. This way you could even provide meaningful error messages in the console for yourself, for example if some button selector stopped working after a Craft update because maybe they changed the markup.
As an alternative solution I see a PHP script that populates the entry before rendering it in the entry edit view. However I don’t know if there is an event in Craft where you could hook into the right place.


Garnish event when changing category group When I am on the categories index (admin/categories), is there a Garnish event that fires when you select a different category group in the sidebar? I want to add some custom JS after the AJAX request completes and the elements have been added to the page.

Craft.elementIndex.on('selectSource', function(){
     alert('changed the source');
});

Craft.elementIndex contains the plugin for all index pages, that means all entries as well as users and categories. There is an updateElements event as well..
Here is a full list

afterInit
selectSource
selectSite
updateElements
selectionChange
enableElements
disableElements
afterAction


Mcrypt in Red Hat Enterprise I'm working at a large organization, where the servers are managed by an IT department. I want to migrate some websites to Craft and asked the IT department to install Craft on a server. The IT department tells me that Mcrypt is not supported by RedHat Enterprise/PHP5.6, so Craft can't be installed

I'm not familiar with server software, are they right? And is it easy to add Mcrypt?

Thank you for helping!

I don't know what version of RHEL they're running, but it could certainly be added.  Whether your IT department will support it or if that breaks some support contract your company has with RH is another question all-together.

FWIW, Craft 3/Yii 2 has done away with mcrypt in favor of OpenSSL, so it's not an issue there.


Best way to handle redesign of large site I have no experience using Craft but will be redesigning a large site using Craft. Most of the content will not be moved or restructured, I'll mostly be making cosmetic changes with HTML and CSS.

What is the best way to redesign a site while it is already live? I'd like to keep the CMS active whilst I'm making changes so that other people on my team can keep adding content before activating certain pages.

Set up a local development environment, and invest in a workflow as described here: Database & Asset Syncing Between Environments in Craft CMS


Get structure top ancestor How can I get the top level ancestor of an entry within a structure? I've tried:

{% set rootEntry = null %}
{% for ancestor in entry.getAncestors() %}
    {% set rootEntry = ancestor %}
{% endfor %}

But that only returns the most recent ancestor back and doesn't go all the way up the chain.

getAncestors() gets all entries that are ancestors. Since you're looping through them what rootEntry is set to last time through is the closest ancestor.

You can avoid the loop and just get the first one:

{% set rootEntry = entry.getAncestors().first() %}


Nginx config for craft working for everything but admin url's I am trying to configure NGINX to serve a craft 2 site.  I am getting the requests being routed through index.php for template url's but not for any admin routes which are redirecting to index.php?p=/admin/**/*.

I am assuming this has more to do with my NGINX config than craft as I have the following option enabled:

'omitScriptNameInUrls' => 'true',

Is there any craft related reason that admin URL's would redirect that way whereas template url's wouldn't?

here is my nginx config:

server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;

index index.html index.htm index.php;

server_name _;

error_log  off;
access_log off;

root /code/public;

charset utf-8;

location / {
    try_files $uri/index.html $uri $uri/ /index.php?$query_string;
}

location ~ [^/]\.php(/|$) {
    try_files $uri $uri/ /index.php?$query_string;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass php:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    include fastcgi_params;
}

# Disable reading of Apache .htaccess files
location ~ /\.ht {
    deny all;
}

# Misc settings
sendfile off;
client_max_body_size 100m;

# 404 error handler
error_page 404 /index.php?$query_string;
}

Update:

just deployed this same app to AWS elastic beanstalk and am running into the same issue with Apache.  This leads me to think maybe it's not related to nginx?

Try adding specific location for admin & cpresources in the nginx config

location ^~ /admin {
    try_files $uri $uri/ /index.php?$query_string;
}
location ^~ /cpresources {
    try_files $uri $uri/ /index.php?$query_string;
}

before

location ~ [^/]\.php(/|$) {


Sending a custom email in the users prefered locale Usecase:

I'm sending out custom emails based on certain events to my users. These users have chosen a certain prefered locale in their profile settings and I'd like for those emails to be in that locale instead of in the locale of the control panel at the time of triggering the events.

So what I'm looking for is a way to set the relevant locale before rendering the email template with twig but I cant seem to find a way.

Relevant code

$mailer = craft()->email;
$mailToBeSent = new EmailModel();

craft()->templates->setTemplatesPath(CRAFT_TEMPLATES_PATH);
$mailToBeSent->toEmail = 'some.email@domain.com';

$mailToBeSent->subject = $subject;

$content = craft()->templates->render(
   '_emails/notification',
    [
        'userInfo' => $this->generateUserInfo($newUser),
    ]

);

$mailToBeSent->htmlBody = $content;
$mailer->sendEmail($mailToBeSent);

Let me know more information is needed or if something is unclear.

You can translate string in PHP and Twig via translate function

public static function t($message, $variables = array(), $source = null, $language = null, $category = 'craft')

Twig

{{ 'my string'|t() }}

PHP

Craft::t('my string');

So all you need to do is to wrap every string in your templates within the translate filter and pass the preferred local as an argument. For example

{{ 'my latest news'|t([], null, currentUser.locale) }}

If no parameter is set, Craft will use craft()->getLanguage() by default so you can do the following as well

$tmpLocale = craft()->getLanguage();
$user = craft()->userSession->getUser();
craft()->setLanguage($user->locale);
$content = craft()->templates->render(
   '_emails/notification',
   [
       'userInfo' => $this->generateUserInfo($newUser),
   ]
);
$craft->setLanguage($tmpLocale);


Get the type of action and the elements(s) that an action is being performed on when listening to elements.onPerformAction? I have a plugin that needs to do something when an entry is deleted. I've recently discovered that the entries.deleteEntry event is not fired when deleting bulk entries (the list view with checkboxes) in the Control Panel (CP). Instead, an elements.onPerformAction event is fired (you can also listen for onBeforePerformAction).

Now that I know that these are the events that are fired when deleting an entry from the list view in the CP, and that I'm working with an Element event instead of a Entry event, I'm struggling to access the type of information I need.

I would like to know...

what type of action is being performed on the element? (Save, Delete, etc.)
how do I identify the entry that the action is being performed on?

It appears that when one or more Entries (or other types of content) are manipulated (in my case, deleted) from the bulk edit view in the Control Panel, the type of events that are triggered are Element events, rather than Entry events.

If you refer to the Craft documentation on elements.onPerformAction, you can see that the 2 params you get access to are action and criteria.

Here's how I was able to find what I needed when working with elements.onPerformAction and the elements.onBeforePerformAction events.

What type of action is being performed on the element? (Save, Delete, etc.)

I was able to capture what type of action was being being performed on my element by looking at the "action" param of the event. Using the following code output the action that was taking place:

$action = $event->params['action']->classHandle; //Outputs 'Delete'

This bit of code will output the string 'Delete'. Perfect.

How do I identify the entry that the action is being performed on.

What I learned is that, when working with an Element event, you're not just working with a single entry. You're potentially working with many Entries, or rather "Elements" to be more specific. Because of this, you can't just grab the Element being manipulated in the same style you can with an Entries event.

$entry = $event->params['entry']; won't work here.

This brings us to the "criteria" param of the Element event.

You can simply grab the "criteria" param of the event to get the elements that the event is taking place on. This param contains an ElementCriteriaModel object.

Viewing the class reference for ElementCriteriaModel shows us what we can do with this object. In my case, I can simply use ->find() on it to get all of the elements I'm working with.

$elements = $event->params['criteria']->find();

I now have an array of the Elements having actions taken on them, stored in $entries.

Now that I have both the type of action and the elements, I have what I was needing to move forward.

Here are my event listeners in full context. One handles a entries.deleteEntry event, and the other handles a elements.onBeforePerformAction event.

craft()->on('entries.deleteEntry', function(Event $event) {
    $entry = $event->params['entry'];
    craft()->lhngroups_organizations->deleteOrgCustomerAddress($entry);
});

craft()->on('elements.onBeforePerformAction', function(Event $event) {
    $action = $event->params['action']->classHandle; //Outputs 'Delete'
    $elements = $event->params['criteria']->find(); //Array of Elements
    if ($action == 'Delete') {
        foreach ($elements as $element) {
            craft()->lhngroups_organizations->deleteOrgCustomerAddress($element);
        }
    }
});

It's important to remember that since we could theoretically be working with many types of Elements (Entries, Assets, Categories, Users, etc.), rather than just Entries, we may need to validate that we're working on the right types of Elements before we operate on them. Since I have multiple event handlers calling my deleteOrgCustomerAddress() service, I did this validation check there.

public function deleteOrgCustomerAddress($element)
{

    // Make sure we're working with an entry in the organizations section
    if ($element->elementType !== 'Entry' && $element->section->handle !== 'organizations') {
        return;
    }

    // We are good to go! Do stuff with the Entry...
}

Thanks to @lindsey-d for some help along the way!


Why does field value get updated on $element->getContent()->fieldHandle but not when accessed directly $element->fieldHandle? I am trying to update a custom field on an EntryModel.  I'm having half success, and I don't understand why. I've looked at other posts such as this one by Brandon which discuss how to assign these values and I'm still not having any luck.

The EntryModel I'm trying to update is available in my field type in the onAfterElementSave method via $this->element.  The handle for the field I want to be updating the value of is available via $this->model->handle.

I have tried using setContentFromPost(), setContent(), getContent()->setAttributes() and they all seem to return the same results.

$fieldHandle = $this->model->handle;

$this->element->setContentFromPost(array(
    $fieldHandle => 'changedValue'
));

// Accessing the value via getContent returns the update value 'changedValue'
$changedValue = $this->element->getContent()->fieldHandle;

// Accessing the value directly returns the 'originalValue'
$originalValue = $this->element->fieldHandle;

Why am I able to successfully update the value for the getContent() method but not when I access it directly on the model?

setContentFromPost() performs an operation on the attached ContentModel, not on the element model itself.

When you initialize a BaseElementModel, its content attributes are set from the associated ContentModel. ("Content attributes" means attributes from custom field data, a.k.a. the stuff you'll typically find in the craft_content DB table for a given element instance.)

However, later updating the properties of the content model does not immediately ripple into changing the attributes of the element model: You'll need to re-save the element after you do a setContentFromPost(), and then its magic attributes will reflect your newly set values.

When you setContentFromPost(), you're changing the data that will ultimately gets passed into each FieldType's prepValueFromPost() method. If you need to do additional processing later (after each FieldType has done its thing) — such as saving records in an third-party table during onAfterElementSave — your service can use getContent() to or getContentFromPost() to grab the values it needs, depending on whether you want to access the raw POST data the user submitted, or the values that got returned from each FieldType's prepValue() method.


Programmatically Setting Entry Type Via Javascript At the moment I'm trying to create a script that is supposed to be run (by chrome extension) on page load (of the new entry page) that with automatically set the entry type. The name of the entry type is "Episodes" and the value (from the html) of the entry type is 5.

Here's the script I have so far.

var contenttype = document.getElementById('entryType');
contenttype.value = "5";

When run, this changes the Entry Type field on the side, but it doesn't actually set the entry type.

How should I go about doing this?

You need to trigger the change() event of the field (after the event handler is attached so not on page load but on $(document).ready()

$("#entryType").val(5).change();


Craftcms commerce product not showing Hi I know my way around CraftCMS and twig a little bit but totally new to the CraftCMS Commerce plugin. I have installed the Commerce plugin and I have added the default templates to get me started. There are a number of example products in a "Clothing" category which I assume the Commerce plugin added during installation.
When I click the "View" button from the edit page of one of those products I expect to see that product in the front end of the website using the example _product.twig template but instead just get the "New Website!" example news item. I don't know how to fix this. I deleted the news item to see what the product would link to instead but all I get now is the Home page.
I can see the product if I click "Preview" in the product editor and see it in split screen.
The URL seems to be correct such as: mywebsite.com/shop/products/ant-001
Can anyone tell me what schoolboy error I'm making?
Thanks in advance.

I selected all in _product.twig and cut and then refreshed the page. Got a blank screen. I then pasted back in and it fixed the page. This was after emptying browser cache twice and trying different browsers that I hadn't previously used on the site. Odd but that fixed it. I was going to delete this post but decided to leave it in case anyone else has this problem. This was developing the site locally, using MAMP and gulp and Tailwindcss.


Only allow SVG as file type I want to have an asset field which only allows .svgs.
To be more specific, I want to upload icons I can later import in my templates via the svg() command. Is this possible without any plugins or a custom field?

You can achieve this using the extraFileKinds config setting like this:
'extraFileKinds' => [
    'svg' => [
        'label' => 'SVG',
        'extensions' => ['svg'],
    ],
],

On your Asset field, check the "Restrict allowed file types?" checkbox, and select "SVG" from the list.


How to send e-mails using utf-8? does anyone know if you can send emails using utf-8 instead of ascii in CraftCMS 2?

I am using the Freeform plugin to send entries from a "Contact Us" form to a CRM that needs to receive the e-mails in utf-8 but they are coming in as ASCII. Is there a way to change this in either the plugin or in Craft?

Thank you!

Craft 2 uses PHPMailer for its email sending library.

It does have a public CharSet property that Craft explicitly sets to UTF-8 when sending emails.

The problem is, they have logic that overwrites our UTF-8 value in certain circumstances... namely when no 8-bit characters are involved in the body setting it to us-ascii: https://github.com/PHPMailer/PHPMailer/blob/master/src/PHPMailer.php#L2453-L2458

Not sure of a good resolution as this seems like undesired behavior in the PHPMailer library to me.

FWIW, the upcoming Craft 3 has ditched PHPMailer in favor of Swift Mailer where it is much more customizable.


Special order filter (by language) in CP for Craft Commerce We have a online-shop for german customers (Craft 2 + Commerce 1) and will expand the shop for american customers (via second domain).
Is there a way to filter the order (status) views in the Backend by domain/language.
The purpose is that the american backend user should only see orders that come via the american domain and the german backend user should see only german based orders.

Not possible with the system by default. Commerce doesn't support multi-store yet (and wont in Commerce 1).

If you want, a plugin could modify the order sources on the left side of the order listing screen using the hook:

https://craftcommerce.com/docs/hooks-reference#commerce_modifyordersources

In this hook you could show/hide sources depending on the user, and add sources for filtering my orderLanguage etc.


Storing Partial Form Completions We're using Solspace Freeform for a multi-stage application form on a client site. We need to store each stage in the CMS - is this possible?

Thanks!

I asked the same question a couple of months back. I was told that it would require some advanced customization to the plugin. It sounded like a pretty big project.


Changing store currency from a plugin Is it possible to change the store currency from a plugin?

I know about COMMERCE_PAYMENT_CURRENCY, but I'm not sure how to set that one early enough.

It also seems like it doesn't affect the displayed price. Do I need to use the commerceCurrency in combination with the cart.paymentCurrency everywhere I display a price?

In your plugin have you tried updating the currency and paymentCurrency fields in the craft_commerce_orders database table?

Depending on when you want to set the currency and how you are determining it, you could either do this by a direct database query, or modify the values in the order model before it is saved using this hook: https://craftcommerce.com/docs/events-reference#commerce_orders.onbeforesaveorder


How to exclude a page from the navigation tree I am looking for a way to exclude certain pages from the navigation. I know it must be quite easy, but nothing seems to work for me at the moment.

So I've setup a lightswitch field "exclude from navigation" (cf_hideFromNav)

Problem is that I want the navigation to start only from a certain slug:

{% set topEntry = craft.entries.section('pages').depth(1).slug('club').first() %}
{% set descendants = topEntry.getDescendants()  %}

    {% nav entry in descendants %}

            {{ entry.title }}
            {% ifchildren %}
{% children %}
{% endifchildren %}

    {% endnav %}

how could I incorporate the cf_hideFromNav in this equation?

any help appreciated!
cheers
stefan

Use a descendantOf parameter with a new ElementCriteriaModel instead of the getDescendants method on your entry model and you can add additional parameters. In your case add cf_hideFromNav as a parameter:

{% set topEntry = craft.entries.section('pages').slug('club').first() %}
{% set navItems = craft.entries.section('pages').descendantOf(topEntry).cf_hideFromNav('0') %}

{% nav navItem in navItems %}
    ...
{% endnav %}

You could also use the parameters id or slug to exclude certain entries:

{% set topEntry = craft.entries.section('pages').slug('club').first() %}
{% set navItems = craft.entries.section('pages').descendantOf(topEntry).id('and, not 23, not 40, not 12') %}

The descendantOf parameter also takes IDs. This would allow you to do this all with just a single ElementCriteriaModel:

{% set navItems = craft.entries.section('pages').descendantOf('1').id('and, not 23, not 40, not 12') %}


How to get a Task's description inside runStep()? I know that I can get the default description of a Task with:

$this->description;
//or
$this->getDescription();

But how can I get the description if it got changed on creation:

craft()->tasks->createTask('Mailer', $new_description);

Adding it as an attribute doesn't seem "right" to me:

craft()->tasks->createTask('Mailer', $new_description, array('description' => $new_description));

The description you define in getDescription() is just the default description in the event that no description was specified when craft()->tasks->createTask() was called.

The actual description for the task is saved on the TaskModel, which you can get via $this->model from your Task class:

$description = $this->model->description;


How can I check a user has completed a field in their profile after log in? I'm sure I've seen this documented somewhere but can't for the life of me find it. After login I need to check the user's profile for an empty field (e.g. phone number) and redirect them to a reminder to complete that field if empty. I guess this can be done via an intermediary page but I'm sure I saw a better solution somewhere. Any help?

If you have a front end form for user registration then you should mark the fields as required in the CMS, you can then make use of Crafts form validation.

I had a project where we imported user data that didn't contain all required fields so needed to redirect users, after they signed in for the first time, to their profile page if data was missing.

I achieved this using a Plugin that contains a service that set a "status" for the current user. The service checked for several different fields and their values and also checked that the user had entered all required fields.

public function setUserStatus( $user ){
    // Get whether user has agreed to current years terms
    $userAgreedToTerms = ( $user->getContent()->agreedCurrentYearsRules == 1 );

    // Use craft validate() function to find ask if user has completed all required fields in profile
    $userHasCompletedProfile = $user->validate() && craft()->content->validateContent( $user );

    if ( $userAgreeToTerms ){
      $userStatus = 'AgreedToTerms';
    }
}

I then used the results of these checks to set a cookie with the "status" of the user.

// Sets a cookie which is used to determine where the user should be re-directed to
$cookie = new HttpCookie( 'userStatus', $userStatus, [ 'expire' => time() + 10 ] );
craft()->request->getCookies()->add( $cookie->name, $cookie );

The function was run from the template using:

{{ craft.pluginName.setUserStatus( currentUser ) }}

And the result of the check was used to redirect the user to the template I needed.

{% set userStatus = craft.request.getCookie( 'userStatus' ) %}

{% if ( userStatus == 'needsToPay' ) and ( site_area != 'payment' ) %}
  {% redirect 'payment' %}
{% endif %}

Hopefully this provides you with enough to create something that works for your case.


How do I set a controller for my homepage How can I set a controller for the homepage? I can't seem to find any way to override the default route to the homepage. I need to call an action from the homepage and can't find any examples of this can be done.

I have a matrixfield with entries in them and want to filter out the matrix blocks that have expired entries on the homepage.

Ok, maybe you can check if the entry in the matrix block is still valid (non-expired) and if that's not the case, just don't render the matrix block? Put everything in a simple if statement?

Something like this (hasn't been tested, use it as an example of what the actual code would be):

{% for block in entry.myMatrixField %}
    {% if block.type == "something" %}
        {% if block.entry.status != 'expired' %}
            {{ block.entry.title}}
        {% endif %}
    {% endif %}
{% endfor %}


Sprout Email compiled_templates I am having an issue whereby a form field is causing errors with Sprout Forms & Sprout Email to function.

I have found the root of the problem in that the field, fullName was causing errors, so changing it to contactFullName seemed like a good idea, as not to confuse matters with Craft's own field fullName.

When checking the logs after making these changes, sproutemail.log was still indicating an error related to the fullName field. Strange! I had changed this! It seems that there is a craft/storage/runtime/compiled_templates/03/****.php where *** is a long string filename used. Going to Settings -> Refreshing the compiled templates did not fix this either, so what can I do to refresh this compiled template to reflect my changes?

Thanks in advance.

You can delete that folder entirely and it will get re-created on the next request that needs a template.

If it's not updating, chances are you've got some PHP byte-level caching extension installed like APC or OPcache that's not busting cache properly.


Get entry by slug with EntriesService in ElementAPI I'm looking to get all entries from one section (say 'videos'), that are related to a specific category. The only reference to the category is the slug that is a parameter in the url:

....dev/videos/category-slug

I need to get the category id from the slug to be able to relate the videos to the category in the criteria:

'criteria' => [
  'section' => 'videos',
  'relatedTo' => ['targetElement' => $categoryId],
],

I can't seem to find a way to get the properties of the category before applying the criteria. Is there something on the EntriesService object that I can use to get the category entry, similar to template usage? E.g:

$categoryEntry = craft()->entries->section('categories')->slug('category-slug');

And then pass the $categoryEntry id through to the criteria to return all the related videos. E.g:

'criteria' => [
  'section' => 'videos',
  'relatedTo' => ['targetElement' => $categoryEntry->id],
],

Any help with a way I could do this all in one endpoint would be great. The alternative is passing the slug into another category endpoint to get the entry, then use the response to pass the id to the above endpoint.

Cheers!

Don't know if this is the most efficient way, but you can always get the category using the ElementsService.

$criteria = craft()->elements->getCriteria(ElementType::Category);
$criteria->group = 'categoryGroup';
$criteria->slug = 'categorySlug';
$categories = $criteria->find();

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'section';
$criteria->relatedTo = array(
    'targetElement' => $categories,
    'field'         => 'relationField'
);
$entries = $criteria->find();


Image Optimize: How do I access specific colors? In the Image Optimize plugin, we have access to the color palette, however it's not clear in the documentation how to access specific colors (https://nystudio107.com/docs/image-optimize/AdvancedUsage.html#color-palette). This works:

{% set optimizedImages = entry.myAssetField.one().optimizedImagesField %}
{% for color in optimizedImages.colorPalette %}
    <div style="background-color: {{ color }}">
    </div>
{% endfor %}

But it returns this which is obviously not a valid CSS background-color:

#06070d
#e0e5e8
#2d539d
#5e92b9
#848484

Which I assume is an array, but I'm not quite sure access each color individually?

Also, it would be nice to know how the order is determined? Light to dark, dark to light? I'm interested in building a background gradient from two colors that match the image.

EDIT: I just noticed that the documentation says, "These colors are sorted by color dominance, and can be used to style other HTML elements with complimentary colors." So, is there a way to choose the 1st and 2nd most dominant colors?

Yep, using your above example, optimizedImages.colorPalette is an array, so you could do:

// Output the most dominant color
{{ optimizedImages.colorPalette[0] }}

// Output the second-most dominant color
{{ optimizedImages.colorPalette[1] }}


Ajax Submit with AM Forms - How To Is it possible to submit to an AM Forms form via Ajax? I cannot find anything in the docs? Is there a tutorial somewhere?

There is an issue open over on their Github, asking about this and the last answer says it's something they are going to add at a later date.

Ajax Sending Issue

So, in short I guess not for the time being.

Edit: I guess if you have the time and fancy the challenge, you could always add it yourself and do a Pull Request?


Entry with many fields vs plugin/custom data structure i'm just getting my feet wet with craft and would appreciate some pointers.

Basically, what i would like to do is show and compare products. Each product will have a description, price, review, and many other characteristics (>50 in total). Items must be searchable by any single or combination of these. Data will be imported through a script (ie not manually).
Apart from that there will be articles etc (with maybe 3-6 fields) on the site.

Looking at the craft content table, it looks like an extra column is created for each field. When there are different types of entries, often many/most columns will be null.

My question is: should i be concerned about:
a) the db structure of craft entries (alternative could be to create separate table for products), especially performance wise

b) searchability of product entries. Would it be easy to search entries by combination of fields?

Not looking for a complete solution, just some pointers i can take along when deciding which way to go :)

Since the data will be imported programmatically, my vote would be to write a plugin that manages these products as a custom thing. There will definitely be a performance benefit to giving your products their own DB table that’s perfectly suited for them, and it doesn’t sound like you’ll be missing any of the features you’d get by having these be actual entries.


CP entry instructions on multiple lines I would like to make instruction field info on multiple lines in CP to improve legibility.
You can make a line return when you input the field instructions but it does not work.

OK I got it. Just after posting this I had a last intuition of trying markdown stuff and it works! Cf Stackexchange line return...
Asking the question gives you the answer!

So just add 2 spaces at end of line!


How do I create a locale dropdown to switch between languages? I’m trying to create a dropdown menu to switch between language’s on my site. I am currently doing this with this snippet found on the google plus community:

{% block locale__switch %}

{# Loop through all of the site locales, except the current one #}
{% set otherLocales = craft.i18n.getSiteLocaleIds()|without(craft.locale) %}
{% for locale in otherLocales %}

    {# Find the current entry in the other locale #}
    {% set localeEntry = craft.entries.id(entry.id).locale(locale).first %}

    {# Make sure that it's actually localized to this locale #}
    {% if localeEntry.locale == locale %}

        {# Output a link to it #}
        {{ locale }}
    {% else %}

        {# Output a link to the hompage #}
        {{ locale }}
    {% endif %}

    {% endfor %}
{% endblock %}

But this simply shows a single link to the opposite locale than the current. Basically I want to have something like this:

EN &#9662;

               English

en &#9662;

               Hungarian

hu &#9662;

This probably seems trivial and simple, but I’m having a tough time figuring out how craft works at this level. Any ideas?

This is because you loop through all but the current locales. Remove the without filter to loop them all.

  {% set otherLocales = craft.i18n.getSiteLocaleIds()|without(craft.locale) %}

.

Add "current" class:

To assign the current locale's link a class of "current", compare the looped locale to the current locale and set a variable that you can later test for. (In the example code I use the ternary operator for short output syntax.)

.

Example Code:

With my example code below you first create an array of all the locales you want the language switch to include, and then loop through it. With this technique you can define the order of the output manually or exclude locales from the loop.

{# Configure and loop through selected site locales #}
{% set locales = ['en', 'hu'] %}
{% for locale in locales %}

    {# Check if locale equals the requested page locale #}
    {% set current = false %}
    {% if locale == craft.locale %}
        {% set current = true %}
    {% endif %}

    {# Is this an entry page? #}
    {% if entry is defined %}

        {# Find the current entry in the other locale #}
        {% set localeEntry = craft.entries.id(entry.id).locale(locale).first() %}

        {# Make sure that it's actually localized to this locale #}
        {% if localeEntry and localeEntry.locale == locale %}

            {# Output a link to it #}
            {{ craft.i18n.getLocaleById(locale).name }}

        {% else %}

            {# Output a link to the hompage #}
            {{ craft.i18n.getLocaleById(locale).name }}

        {% endif %}

    {# Not an entry page #}
    {% else %}

        {# Output the same path with the locale's base URL (`siteUrl`) #}
        {{ craft.i18n.getLocaleById(locale).name }}

    {% endif %}

{% endfor %}

Code edits done to implement a lookup of the (translated) locale name as described here by Brandon Kelly

.

Notes:

The easiest (and recommended) way to use this language switch is to exclusively use    entry pages (channel entries, structure entries, or singles) on your site.
All non entry pages have to have the same URL path / slug for each locale (eg. http://craft.dev/de/meineindexseite/ and http://craft.dev/en/meineindexseite/), translated URL parts won't work for non entry pages with this code.
If you only use entry pages or if you are using localized template folders you should be save to remove the entry is defined conditional (incl. the else part) altogether.
craft.config.siteUrl[localeId] only works if siteUrl is configured to take care of localized URLs


Display all fields without knowing object type? I was looking for a way to show all fields/properties of a given object, and came across this useful tidbit: How to display all fields belonging to current entry?

I'm new to Craft/Twig and didn't actually know what type of object I'm trying to output properties of. I'm not sure when I output the object with {{ mysteryObject }} it outputs a number. That doesn't seem useful.

When I do the loop like in the question I referenced above like:

    {% for prop in mysteryObject.getFields() %}
        {# get the field Model from the fieldId #}
        {% set field = craft.fields.getFieldById(mysteryObject.fieldId) %}
        {# print the field handle and the field content  #}
        {{ field.handle }}
        :
        {{ entry.getContent()[field.handle] }}
    {% endfor %}

I get the error:

  Calling unknown method: craft\elements\MatrixBlock::getFields()

Cool, so now I know my object is a MatrixBlock, but this makes me wonder how I would go about inspecting the properties of just any object, like you can in JavaScript, without knowing what the object is.

You can

<pre>
{{ dump(myObject) }}
</pre>

And see it's type and attributes. You can as well use {{ dump(Object.getAttributes) }} with nearly everything in Yii2. If it's just about getting to know what object you currently have this function will be your friend once you know how to use it. Another approach would be much simpler yet more powerful: take a look at the source code or enable intellisense for your IDE and let your IDE show you everything


Migrate multiple Craft 2 CMS sites on cPanel I am completely new to Craft CMS but need to migrate multiple sites at a current hosting provider away to AWS.

Due to a hard deadline, I have been looking at a lift and shift approach for the time being - using a cPanel AMI in AWS and then moving the sites across.

  Does anyone have any experience of moving sites from cPanel to cPanel particularly Craft?

I’ve tried one site already but get a 500 internal server error when trying to browse the site. I’ve amended the db.php file to connect to the database and that looks ok.

Could anyone give me some pointers on the best way to move the sites and anything I need to look out for along the way?

Any pointers or recommendations would be really helpful.

Thank you.

Have you checked the permissions on the sever? As 500 usually comes due to server permissions or due to wrong .htaccess or wrong Rewrite file. Have a look at .htaccess file.
And make sure to check your server error logs, they might provide you some valuable input for the errors.

If you find some specific errors, please share them so the community could help you better.


$_SERVER['REMOTE_ADDR'] vs craft()->request->userHostAddress The typical way to get your user's IP address via PHP is with $_SERVER['REMOTE_ADDR']. This is pretty solid, but can lead to some IP detections that are surprisingly far away from the user's actual location.

Craft also has it's own IP detection with craft()->request->userHostAddress. This jumps through a few more hoops before finally falling back to $_SERVER['REMOTE_ADDR'].

Which is better in terms of geolocation accuracy?

The Craft docs say this:

  Considering any of these server vars besides REMOTE_ADDR can be spoofed, this method should not be used when you need a trusted source for the IP address. Use $_SERVER['REMOTE_ADDR'] instead.

I don't think my source needs to be that "trusted". I'm using the IP address for best-guess geolocation, not for any sort of security purposes.

I'm just looking for whichever one will pinpoint closest to the human user.

Disclaimer: I'm well aware that IP detection is a lousy way to pinpoint users, and that HTML5 / JS offers much more accurate geolocation results. But when using that method, geolocation is optional to the user, and they may deny permission to share their location. It's good to have the IP detection as a fallback.

Between the two, I'd say that craft()->request->userHostAddress is going to be a more reliable method.   It tries to take into account things like clients going though proxy servers, shared ISP IP addresses, etc. whereas you don't know any of that just relying on $_SERVER['REMOTE_ADDR'].

But, as you pointed out, none of this is guaranteed to be reliable.


Sort Categories by Entry Updated I have the following Category loop code which I'm trying to sort by the date the entries within have been updated.

  e.g if an entry was just updated within a category, this category
  would be at the top of the page/loop.

Here's my code

  <!-- START CATEGORY LOOP -->
  {% set categories = craft.categories()
      .level('1')
      .limit('8')
      .all() %}

  {% for category in categories %}

       {% set offers = craft.entries({
            relatedTo: category,
            with: ['offerLogo'],
            limit: 10,
       }).all() %}

       {% for offer in offers %}
          {% include '_card' %}
       {% endfor %}

  {% endfor %}

I just can't get them to be ordered. Any help would be great!

I am not sure if i get what you mean, do you want to have the categories as content blocks, which show the entries ordered by last updated, but the category blocks should be ordered as well e.g. if entry x in categort y is the newest the category block y should be on top of the list?

Otherwise that should work, displaying the latest 10 updated entries on top for 8 categories all in descending order relative the the update date

   {% set categories = craft.categories({
         level: 1,
         limit: 8,
         orderBy: 'dateUpdated desc',
     })
  %}

  {% set offers = craft.entries({
     relatedTo: categories,
     with: ['offerLogo'],
     limit: 10,
     orderBy: 'dateUpdated desc',
     })
   %}

   {% for offer in offers %}
      {% include '_card' %}
   {% endfor %}


Why am I unable to use Twig conditional on entry.type property? Where entry.type is equal to meetingsEventsOverviewPage, I would expect the following to return true:

{{ entry.type starts with 'meetingsEvents' }}

And

{{ entry.type in ['meetingsEventsOverviewPage', 'meetingsEventsContactPage'] }}

However that doesn't happen.

If I test the string explicitly, it does work:

{{ 'meetingsEventsOverviewPage' starts with 'meetingsEvents' }}

And

{{ 'meetingsEventsOverviewPage in ['meetingsEventsOverviewPage', 'meetingsEventsContactPage'] }}

Is there some kind of parse order going on here that I need to know about?

Your problem is that entry.type is actually not a string, but an instance of EntryTypeModel. This means that entry.type is an object containing many different properties, among them the handle, which would be the property that you want to test in this case.

In other words, this should work:

{{ entry.type.handle starts with 'meetingsEvents' }}

Tip: When in doubt about the data your working with, or stuff not working like you'd think, it's often a good idea to dump:

{{ dump( entry.type ) }}

This will output all sorts of useful information about the data, e.g. what it actually is (String, Object etc), all its properties and methods etc.


Allowing a new locale to fallback on content from a default locale? I am setting up a localized site that defaults to English (en_us). Alternate locales will have URLs such as example.com/fr

I would like to ensure that users browsing the French website don't accidentally end up back on the default locale. My problem is that some sections will not target the French locale but I would still like the URL to display the default, English content with the /fr/ URL.

If I uncheck targeting for that locale in my section settings, then browse to the entry (example.com/fr/section/entry) I get a 404. How can I display the default English entry content at that URL?

One solution (without needing to create a custom plugin) would be to add a lightswitch or checkbox field called useDefaultLocale, and add it to the field layout of any sections that you want to default to english. In your template you can test for the value of this field and display the default locale version of the content. You would of course need to target 'fr' locales for any sections that included this functionality.

{% if not craft.locale == 'en' and entry.useDefaultLocale %}
    {% set entry = craft.entries.section(entry.section).locale('en') %}
{% endif %}

Any content that is defined directly in the template using the translate filter (i.e. {{ 'Date'|t }} ) would still get translated of course, but maybe that's a good thing. There also may be a way to manually set the locale so as not to translate these as well, that I don't know about. If anyone knows, please leave a comment, and I'll add it to the answer.

Update: carlcs brings up a good point regarding SEO and duplicate content. To solve this you could define a canonical link using: (placed in the if clause above)

{% set canonical %}
    <link rel="canonical" href="{{ entry.url }} />
{% endset %}`

and then in the _layout template head:

{% if canonical is defined %}{{ canonical }}{% endif %}

The side effect is that some French users might get directed to the english url from search engines. Pick your poison I guess.


Craft Commerce multisite, different tax rates In Craft 3, Commerce 2 is there a way to set a different tax category or rate on a cart/site when using commerce in a multi site environment? Site A (b2c website) has tax rate 1 (21% with tax included in price) and site B has tax rate 2 and 3 (21% with tax excluded in price and a 0% tax rate). Both sites use the same products/inventory but are targeted for different audiences (b2c and b2b).

I’m looking for a solution that works simular like posting  to the update-cart action when adding products to the cart.

Or, even better would be to be able to set defaults for the cart when setting {% set cart = craft.commerce.carts.cart %}.

As of Commerce 2.0, there is no support for multi-site apart from a product’s custom field information.

A cart exists in the session, once per Craft installation, and there are not separate carts per site.

Multi-site is something we plan to add in the future.

Having said that, a cart stores the current orderLanguage based on the current language of the site the order is being made in. A custom adjuster could be written to add custom tax costs based on this information: https://github.com/craftcms/commerce/blob/develop/docs/adjusters.md


Craft 2 CMS - How to change Limits in Dashboard I'm very new to Craft CMS.

The company I work for, has their website build with Craft. The website was build by a 3rd party company, Now they gave me the responsibility to give the site a facelift.

Currently I'm struggling to increase the limit of services displaying on the home page.

We have 4 services, but only 3 display.

In the back end of Craft Dashboard, I can only assign 3 services, can I increase this to 4?

And if I can, how can I do it?

Looking forward to some feedback.

If the account you're using has admin rights you could do so by going to:
Settings > Fields > [Field label of your service display] and edit it. On the bottom there should be a input which sets the limit of your displays to 3.

You should only check with the person who build your website if they didnt set the limit in the code to 3. If so he has to change that.


Plugin using event listener throws error using $this I have written a plugin to hook into an event raised by a contact form plugin. I am running PHP 5.6 locally, and the plugin works just fine. Moving the code to a server running 5.3 (which I cannot change) leads to an error. My init() looks like this:

public function init() {

   /* Intercepts the Capture form submission */
   craft()->on('capture_submissions.onBeforePost', function(Event $event) {
      $data = array(
         'email_address'   => $capture_data['email'],
      );
      $result = $this->addMember($data);
}

When submitting the form, I get the following error:

Fatal error: Using $this when not in object context in /home/mysite/craft/plugins/myplugin/MyPlugin.php on line 69

By changing the plugin to use MyPlugin:: instead of $this-> leads to an error in Craft core:

Fatal error: Using $this when not in object context in /home/mysite/craft/app/etc/components/BaseSavableComponentType.php on line 41

What is the correct way to call my plugin methods when running as an event listener?

Seem to be doing well at asking and then answering my own questions.
If anyone has the same issue as me, it is because you cannot use an anonymous function in the callback. With my example above, the correct way is thus:

craft()->on('capture_submissions.onBeforePost', array($this, 'onCaptureListener'));

public function onCaptureListener(Event $event) {
 ...
}


Display a specific image from assets I'm trying to grab a specific image to display that is located in assets. I tried using {% set image = craft.assets.filename('image_filename.jpg') %} but I get the error "An unknown image object was used." I also tried referring to one of the asset sources which I saw as a solution in another post related to my question: {% set image = craft.assets.source('my_images') %} but I'm not sure how that would help me grab a specific image. {% set image = craft.assets.images[0] %} just grabs an image from any of the asset sources if I change the index number. What am I doing wrong here?? Thanks in advance!

You can do

 {% image = craft.assets.id(x).first() %}

Where x is the ID of your element. You can see the ids of your elements in your cp. There is a little wheel icon below your asset sources where you can define which attributes to display. Just check the selectbox for id

You can learn more about fetching entries with ElementCriteriaModels in the docs

Your problem was: you did not fetch the element. You prepared your database query but you need to execute it with first() or find() because


Craft Commerce payment methods per user Is it possible to allow certain payments per user in Craft Commerce and if so how and if not how would it be possible?

Just breaking my head around it.

There are a variety of ways you can solve this depending on your needs.

One possible way would be to assign users to groups and then use simple twig code to limit the shown payment options at the template level depending on which user (i.e which user of which group) is viewing the page.

In addition, some validation logic in a custom plugin should probably be used to prevent accidents in case a user does somehow submit a payment of a type you don't want them to be using.  However I don't necessarily see an ideal event to listen to for that - I'd check with Luke Holder but perhaps onBeforeSaveOrder would work - see https://craftcommerce.com/docs/events-reference#commerce_orders.onbeforesaveorder

Basically it comes down to how you'll be differentiating these users - without more info it's hard to provide a more substantial answer.


Can you use Craft to build a relational web app database in a Knapp or Caspio style? I guess the answer is probably "No" but I have read this "relate anything to anything" feature here http://buildwithcraft.com/features/relations and I was wondering how powerful is that.

I want to create an Events website

In my project users should be able to:

Enter records via a form (Events)
Change their own records
Choose an event and say they attend it (subscribe)
Enter or choose how the travel to that event (by car, bus, plane)
To rate and add a comment to those events.

The Events should show for instance how many people attend to that event, who are those people and how they travel there.

Ideally users should be able to sell their own even tickets but that will need some custom developing for implementation.

I could reach that kind of functionality with an SaaS database online solution like knapp or Caspio, create their a relational database and embed their database views in a CMS like Craft but I would prefer to use just Craft for the whole project.

Would be that possible to build all that in Craft?

It is perfectly possible. You would probably need a channel for the events and perhaps a separate channel for interactions on the event (ratings, comments etc). You can use Guest Editions or create your own plugin to add entries via a form.


Error with Craft Commerce & Stripe no longer supports API requests made with TLS 1.0 I am using the code from the example templates to integrate a simple stripe pay button on a commerce site:

<form method="POST">
  <input type="hidden" name="action" value="commerce/payments/pay"/>
  <input type="hidden" name="redirect" value="/orders/order?number={number}"/>
  <input type="hidden" name="cancelUrl" value="/checkout/payment"/>
  {{ getCsrfInput() }}
  {% if cart.paymentMethod.class == 'Stripe' %}
  <script
    src="https://checkout.stripe.com/checkout.js"
    class="stripe-button"
    data-label="Pay Now"
    data-key="{{ cart.paymentMethod.settings.publishableKey ?? '' }}"
    data-name="{{ siteName }}"
    data-image="/assets/img/tfa-logo-128.png"
    data-description="Membership" {# This is not used for order description in stripe - see Craft Commerce general settings #}
    data-email="{{ cart.email }}"
    data-currency="{{ cart.paymentCurrency }}"
    data-amount="{{ cart.totalPrice|commerceCurrency(cart.paymentCurrency,convert=true,format=false) * 100 }}"
    data-locale="auto">
  </script>
  {% endif %}
</form>

When the form submits I get back the following error:

  Stripe no longer supports API requests made with TLS 1.0. Please
  initiate HTTPS connections with TLS 1.2 or later. You can learn more
  about this at https://stripe.com/blog/upgrading-tls.

Is this something that needs updating in the commerce plugin? I am running my local site using HTTPS using Valet. I found this link which suggests it might be the plugin that needs updating (I am using the latest version of craft commerce).

This is an issue with your local install of OpenSSL curl/PHP or some other system level component.


Custom title using URI segment I am working on my SEO and I am getting a duplicate title in Craft.
I want to make a custom title using the URI segment in using PHP.

You can use something like this in your main layout template. You'll need to add a filter after "segments" to get the URI segment you want, e.g.: |first or |last, and you'll also need to |replace any hyphens and then |capitalize the first letter of the result.

{% set myUri = craft.app.request.segments %}

<title>{{ myUri }}</title>

For more on segments: https://docs.craftcms.com/v3/changes-in-craft-3.html#template-functions