Redactor extension plugin loading JS before Redactor.js As I want to use two different Redactor plugins, table.js and properties.js, I decided to write a simple Craft Plugin to load the JS using includeJsResouce in the init() function, as so;

function init() {

    if ( craft()->request->isCpRequest() && craft()->userSession->isLoggedIn() )
    {
        craft()->templates->includeJsResource('myextensions/js/properties.js');
        craft()->templates->includeJsResource('myextensions/js/table.js');
    }

}

However, I have found that these JS files are being loaded in the HTML before the Redactor.js file, so I get a JS error in the console, as Redactor is undefined. [Uncaught TypeError: Cannot read property 'prototype' of undefined]

Is there a way to ensure that my plugin JS is loaded after Redactor that does not entail hacking the core of Craft?

The version of Craft I am using is the current, Craft Pro 2.5.2753.

You need to alter your properties.js and table.js files. Instead of assigning the plugin function to $.Redactor.prototype you should assign it to the RedactorPlugins object.

Standard Redactor Plugin setup:

$.Redactor.prototype.myplugin = function() {
    return {
    // Plugin code here...
    }
}

Craft CMS Redactor Plugin setup:

// Initialize the RedactorPlugins object if it doesn't exist
if ( !RedactorPlugins ) { var RedactorPlugins = {}; }

// Assign the redactor plugin function
RedactorPlugins.myplugin = function() {
    return {
    // Plugin code here...
    }
}

I'm not sure where the documentation on this is, but you can see it in Pixel & Tonic's own RedactorClips plugin here:  https://github.com/pixelandtonic/RedactorClips/blob/master/redactorclips/RedactorClipsPlugin.php


Navigation Slug Issue (Structure Section) I am trying to setup a navigation on a site. I am using a Structure Section called "pages", however, when I changed the "Top-Level Entries" to just {slug} and the nested levels to {parent.uri}/{slug}, I am getting URLs like about/profile-1 and about/biography-1.

I am guessing the reason why I am getting -1 is due to the fact that the entry already exists in my About channel.

Any thoughts on how to resolve this?

If the navigation section is strictly for structuring your navigation I would disable 'Entries in this section have their own URLs' and add a entries relation field to connect your content with the navigation items.

A standalone plugin could also help you out: https://github.com/am-impact/amnav


A&M Forms reply to address I'm using A&M forms which is working great. However when a form is submitted the reply to address is the address set in the Control Panel. Ideally one could fill this in with a variable so that it uses the email address submitted by the end user.

is this possible?

Of course a couple of minutes after posting this I find the answer.

All you need to do is put the email field handle in the reply to email address input like this

{emailAddress}


How can I make an oversized chalkboard organiser? I found this ( http://www.pbteen.com/products/oversized-chalkboard-organization/ ) on PB Teens and Pinterest and fell in love. It's perfect for me but at a price of around £200 is a bit ridiculous! Anybody got any ideas on how I might DIY this?

Thanks in advance :)


Enable the user to upload multiple background Images that come from a matirx loop I am trying to enable the user to have mutliple full width css background images, my loop works going through the matrix and grabbing the images but the trouble is they all have the same css class mid-banner and one overrides the other so they all end up being the same image, how can I make it so that each one has a different class as it loops through, or each have an individual id would probably make more sense.

Thanks in advance for any help

{% for block in entry.homeMatrix %}
    {% if block.type == "homeMatrix" %}
    {% set oddOrEven = cycle(['even', 'odd'], loop.index0) %}

{{ block.txtTitle }}

                {{ block.txt }}

        {% for image in block.image %}

        {% endfor %}

{{ block.imageTitle }}

    {% endif %}
{% endfor %}

So I have figured out the answer to my own questions it turns out that I needed to use a {{ counter }} that incremented the class name in both the  tag where the .mid-banner class is defined so that each time the loop runs it add 1 to the class. The stars show the code i have added:

{% for block in entry.homeMatrix %}
    {% if block.type == "homeMatrix" %}
    {% set oddOrEven = cycle(['even', 'odd'], loop.index0) %}

{{ block.txtTitle }}

                {{ block.txt }}

        **{% set counter = ( counter | default(0) ) + 1 %}**
        {% for image in block.image %}

        {% endfor %}

{{ block.imageTitle }}

    {% endif %}
{% endfor %}


Class not found error when running unit test on a plugin service I am writing a plugin and want to unit test my services.  I am following the example given here: https://github.com/amacneil/cocktailrecipes. The problem is when I run my application, I get a

PHP Fatal Error: Class 'TournamentData_IndividualService' not found.

Here is the problem portion of the test code:

<?php
namespace Craft;

use \Mockery as m;
use PHPUnit_Framework_TestCase;

class TournamentData_IndividualServiceTest extends PHPUnit_Framework_TestCase
{
    public function setUp()
    {
        $this->ingredientRecord = m::mock('Craft\TournamentData_IndividualRecord');
        $this->service = new TournamentData_IndividualService($this->ingredientRecord);
    }
}

Here is my service code:

<?php
namespace Craft;

class TournamentData_IndividualService extends BaseApplicationComponent
{
    protected $individualRecord;

    public function __construct($individualRecord = null)
    {
        $this->individualRecord = $individualRecord;
        if(is_null($this->individualRecord)) {
            $this->individualRecord = TournamentData_IndividualRecord::model();
        }
    }
}

One more note, just in case this has the answer to what I'm looking for, I have taken a look at https://github.com/selvinortiz/craft.loath, but I wasn't able to follow what its setup code was accomplishing.

Any help is greatly appreciated!

I figured out the problem, I needed to load in the service, and then my service needed to load in the model and record. So for the test code, I added the function:

protected function loadServices()
{
    require_once __DIR__ . '/../services/TournamentData_IndividualService.php';
}

Then for my setUp function, it became:

<?php
namespace Craft;

use \Mockery as m;
use PHPUnit_Framework_TestCase;
class TournamentData_IndividualServiceTest extends PHPUnit_Framework_TestCase
{
    public function setUp()
    {
        $this->loadServices();
        $this->ingredientRecord = m::mock('Craft\TournamentData_IndividualRecord');
        $this->service = new TournamentData_IndividualService($this->ingredientRecord);
    }
}

Then in my service method, I added require statements for the model and record like so:

<?php

require_once __DIR__ . '/../models/TournamentData_IndividualModel.php';
require_once __DIR__ . '/../records/TournamentData_IndividualRecord.php';

namespace Craft;

class TournamentData_IndividualService extends BaseApplicationComponent
{
    protected $individualRecord;

    public function __construct($individualRecord = null)
    {
        $this->individualRecord = $individualRecord;
        if(is_null($this->individualRecord)) {
            $this->individualRecord = TournamentData_IndividualRecord::model();
        }
    }
}

Ironically, I managed to find the answer to my problem almost immediately after deciding to ask the community, but hopefully this helps somebody else in the future!


Images uploaded or static I am very new to Craft CMS and going through the introduction videos on Mijingo.  I am new developer also so please answer in easy terms if you can. I need to know what the difference is between an image I might drop straight into the assets file (if I choose) or the uploaded ones through Craft. I understand that you want to use images in the CMS they NEED to be uploaded through Craft. BUT why would you use "static" images straight into the assets file? My colleague said if you want to use interface pictures you drop them straight in. But I don't understand what that means. Thanks very much and have a great day.

Jason

P.S. Please say why if this was a bad question so I can become better at asking on Stack Exchange. Thanks again!

Great question! Let's define some terminology to make this easier to discuss...

Static images: Uploaded via FTP (or similar). Not tied into the CMS in any meaningful way.
Dynamic images: Uploaded via the Control Panel (or synced after FTP upload). Can easily be related to entries and other elements, or even have fields assigned directly to your assets.

Static images are the more "traditional" way of storing images, just as you would with a non-CMS website. There are absolutely some good reasons to use static images... for example, anything on your website which will basically never change (like the company logo).

Dynamic images (aka "Assets") are ideal for dynamic content. If you're writing articles with images, this is a perfect use-case. There are far more complex examples as well, but this is a great starting point.

If an image makes more sense being static, then let it be static. Conversely, if you believe it needs to be dynamic, then make it dynamic. Don't try to force an image to be something that it's not. With just a little bit more experience, it will quickly become obvious which kinds of images should be static vs dynamic.

Here's how I've got my folder structure setup...

/craft
/public
    /assets
        /(ASSET SOURCE FOLDER 1)
        /(ASSET SOURCE FOLDER 2)
        /(ASSET SOURCE FOLDER 3)
    /resources
        /css
        /js
        /images

My static images go into /public/resources/images. They are then referenced just as if the site were not using a CMS at all.

My dynamic images go into various subfolders within /public/assets. Each subfolder maps directly to an Asset Source, defined in the CMS control panel.

  NOTE:

  Make sure your assets subfolders have proper read/write permissions! Craft will need to interact with those files when uploading, and also when creating image transforms.

  Permissions for your static folder can be much stricter... Those will only need to be read, never written to.

Of course, this all assumes that you're storing your dynamic images in a local folder... Things are slightly different when you want to keep your assets in the cloud (S3, Rackspace, Google), but that's a different conversation altogether.

Hope that helps!


MySQL Collation: utf8mb4_unicode_ci (emojis) The Craft docs call for using utf8_unicode_ci for MySQL collation. MySQL 5.5.3 introduced support for utf8mb4_unicode_ci, which, I believe, is required to support the storage of emojis.

Does anyone have experience running Craft with the utf8mb4_unicode_ci collation? Any issues to watch out for?

When you create a database in MySQL in Craft 2, you can set the default charset and collation, so that any SQL statements that get executed that don't explicitly specify what charset/collation to use, MySQL will fall back on those.

Craft 2 will always explicitly set what to use based on what the charset and collation database config settings are set to in (by default utf8 and utf8_unicode_ci).  Craft 3 does away with this and falls back on the database default.

However, if you set those config settings to utf8mb4 and utf8mb4_unicode_ci and try to install Craft 2 you'll run into errors:

CDbCommand failed to execute the SQL statement: SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes.

Because MySQL's utf8 implementation uses 3 bytes per character and utf8mb4 uses 4-bytes, that pushes many of Craft's indexes over InnoDB's 767 byte limitation.

It's worth noting that if the only place you think you'll need 4-byte support for emojis is in a Rich Text field, then Craft will automatically HTML encode them so they fit in MySQL's 3-byte utf8 charset.

If you need them outside the context of a Rich Text field, then your best bet would be to manually set just that column's charset and encoding to use mb4 in the database directly.

It's also worth noting that the upcoming Craft 3 supports PostgreSQL where none of this matters and it just works.


How to display a featured image in the list of entries I created a field which uploads an image, and I want it to display it for each of my entries inside my for loop.

What's the code I should use to do it?

{% for element in elements %}
    {% set asset = element.assetFieldHandle.one() %}
    {% if asset is not null %}
        <img src="{{ asset.getUrl()">
    {% endif %}
{% endfor %}

Take a look at ElementQueries and how to handle errors


Prevent to upload any kind of file on Asset menu I made two different types of Assets: one for images and one for PDF.
They works in 2 differents folder to avoid to mix them.

Using them inside entries it works good, if I try to upload something different I receive an error message.

If I click Assets on the main Menu (not inside entries) I'd like limit the upload to the asset I choose.

It means that I would like prevent to upload a pdf on asset images and vice versa and I'd like also to prevent uploading of any different file types.

Not sure if Im doing something wrong or its the natural behaviour of CRAFT.

The ability to restrict the allowed file types is defined on a per-field level.

In order to do what you're looking for, it would have to be defined on a per-asset source level, so no... it's currently not possible natively.


exclude array of entry types in query Here is my query:

{% set resources = craft.entries({
    section: 'resources',
    type: 'not caseStudyLanding'
    relatedTo: filterParams,
    orderBy: 'postDate desc'
}) %}

I would like to exclude two entry types (caseStudyLanding and webinarsLanding) but I have been struggling with the syntax.

I found it here: https://docs.craftcms.com/v3/dev/element-queries/entry-queries.html#parameters

        type: ['not', 'webinarsLanding', 'caseStudyLanding'],


Global Site Variables (Static Page?) On various Craft sites, I've needed to provide my clients with access to certain variables used across the site. Things like open hours, specific seasonal color palettes, on / off operation toggles. In the past I have made a Static page that has a single table field with name and value pairs. I have then retrieved these values at the start of my layout template and output them on various pages as needed.

1) Is this this best way to do this?

2) Related question (and more pressing): For a recent project, I have been unable to grab the variables as I've done in the past. Not sure why...

{% set theRows = craft.entries.section('theSection').one() %}
{% set siteVariables = [] %}
{% for row in theRows %}
  {% set siteVariables = siteVariables | merge({ (row.name): row.value}) %}
{% endfor %}

My section entry query is coming up blank and dumping siteVariables causes a server error.  The set up seems the same as a working installation. Am I missing something? craft.entries.sectionId(ID).one() also doesn't see to work...

Define "best". It's one way of doing it but has a couple of issues. They need to log in to see this (I presume, otherwise one issue is that there are public facing things on the website no actual visitor cares about) but it's not in the dashboard. So there's a log in then navigate to the front end and get the page workflow which is less than ideal) Why not just put them in a global table field and let the client view/copy/edit them there?
Your merge needs square brackets. You're trying to merge an object not an array. Try

{% set theRows = craft.entries.section('theSection').one() %}
{% set siteVariables = [] %}
{% for row in theRows %}
  {% set siteVariables = siteVariables | merge([{ (row.name): row.value}]) %}
{% endfor %}


Use postDate in section title format field I'm trying to generate titles for a section's entries based off of the given post date (if it exists). Here's the configuration I've got in the Title Format field for this section's entry types:

New Arrivals for {% if postDate %}{{ postDate|date('M j, Y') }}{% else %}{{ now|date('M j, Y') }}{% endif %}

I expect that, upon saving each new entry, Craft would build a title based off of the post date. Unfortunately, it always builds off of the current date - even with a more straightforward title format configuration:

New Arrivals for {{ postDate|date('M j, Y') }}

I understand that the user doesn't have to fill out the post date fields, but it appears that Craft creates a post date for every entry (and even does so before it writes the date created field to the database).

With that in mind, why wouldn't the above title format configurations work? Am I missing something? Any and all help is appreciated.

The entry will be passed to this template as a variable named object. When you want to reference its properties you have two options:

{postDate} (single braces)
{{object.postDate}} (regular Twig syntax)

The first one is just a shortcut for the second one. When Craft is getting ready to pass your Title Format template off to Twig, the first thing it will do is find any of those shortcut tags and swap ten with the full Twig syntax.

So in your case here's what you should do:

New Arrivals for {% if object.postDate %}{postDate|date('M j, Y')}{% else %}{{ now|date('M j, Y') }}{% endif %}


How can I return only 1 random block in a Matrix in Craft using Twig? I have a matrix with a couple of text fields for a caption, location and URL and an image

Every time this page loads I want a random slide to show - so the background image is random, as well as the relevant text fields.

I've tried several variations of the below but keep getting a template error of "Array to string conversion"

Why is this happening? How can I achieve the desired result?

{% if entry.carouselMatrix is not empty %}
    {% set currentSlide = shuffle(entry.carouselMatrix.slides).first() %}

        {% for slide in currentSlide.first() %}
            {% set image = slide.image.first() %}

                    {{ entry.heroText }}

                    {{ slide.caption }}

        {% endfor %}

{% endif %}

You can create a random order by including rand() in your OrderBy function.

{% set randomBlock = entry.carouselMatrix.orderBy('rand()').one() %}
{% if randomBlock is not null %}
    {% set randomSlide = randomBlock.slides.orderBy('rand()').one() %}
    {% if randomSlide is not null %}
        {{ randomSlide .caption }}
        {% set image = randomSlide.image.one() %}
        {{ image is not null? image.getUrl() : '' }}
    {% endif %}
{% endif %}


Is there a way to determine if an order requires shipping? We're selling a mix of both tangible and digital products with Commerce.

If an order doesn't require shipping, I'd rather just take them to directly to the final one page checkout/payment form.

Is there a way to determine this natively or do I need to add a "RequireShipping" field and loop through the line items to see if one exists in the user's cart?

Commerce_OrderModel has a getShippingMethod() that will return a Commerce_ShippingMethodModel class of the current shipping method, or null if nothing has been set.

If you've already got the order in the template is should be as simple as:

{% if order.getShippingMethod() %}
    Shipping.
{% else %}
    No shipping.
{% endif %}


Clear cache tool missing I'm trying to clear templates cache. The Craft CMS 3 documentation says:
 You can also manually clear all of your template caches from the Settings page, using the “Clear Caches” tool.

When I go into Settings, I don't see any options to clear the cache there, nor is it within any of the other options there (General, Sites, Routes, etc). Do I have to enable the utility somehow?  Thanks in advance for your help.

The documentation is out of date.  The cache tools now live under the Utilities section.  Presumably you need admin privileges to see/access/use these tools.


Is there any way to prevent Craft from doing anything with uploaded GIF assets? I'm having an issue where Craft seems to change (significantly slowing down) the framerate of animated GIF assets on upload (this doesn't seem to be an image transform problem: if I add the file as an asset in Craft, and then open the uploaded version of the file, the framerate has already changed).

The server is on the latest version of php-imagick (3.1.2) and ImageMagick (6.6.7-10) that are currently available for the version of Ubuntu that we're running (14.04 LTS)

So my question is: is there any way (config setting or similar) of preventing Craft from messing with uploaded GIFs in this way?

When you upload an image to Craft, the image is automatically “cleansed” using the same basic process that Craft uses to create image transforms. That happens to ensure that there are no malicious scripts hidden in the images, and it’s not something you can disable.


How can I replace a newline (in a plain text field) with a comma? I need to convert a new line in a plain multiline text field in Craft into a comma.
My text looks like:
1 Infinite Loop
Cupertino, CA

and I want to convert it to: 1 Infinite Loop, Cupertino, CA
I tried doing {{ text|nl2br|replace({ '<br>', ', ' })|raw }} but that didn't work.

I figured out that the best way to do this was to replace the newline character \n.
Final code:
{{ plainText|replace({ "\n" : ", "}) }}


Is there any way of converting an existing field to a Matrix? I'm working on an existing site that has an "Entries" field that allows authors to provide a selection of related articles. However, since some articles have titles whose meaning is not entirely clear in this different context, the client would like to be able to tweak the wording of the titles in this "related articles" context.

The best way I can see to do this would be to make the "Related articles" field a Matrix, with each block containing both an entry and an alternative title. However, this is an existing site with lots of posts that already use this field, so I'd need to somehow convert the existing "Entries" field to a Matrix. Is this possible at all?

(I realise that an alternative approach would be to add a "Short title" field to entries. However, UX-wise this feels awkward compared to the Matrix approach, since it would require the editor to also potentially edit each of the related articles, which is both more long-winded and less clear as a process)

Unless each time an Entry is selected the name needs to be different (to other times that same Entry is chosen), then I would suggest using your latter approach of adding an secondary Title field as it would be more efficient in the long term because the secondary Title would only need to be added once.

If it's about an Entry, consider keeping it 'with' the Entry.

I use a similar approach for Meta Titles to override the Entry title for SEO purposes.


Update Plugin's config.php Is it possible to update the config.php file in a plugin outside of manually opening and adjusting the array? I'm hoping there's a way I can have a certain user group be able to change the array values with the plugin's control panel page.

The config file is very simple, it looks like this:

<?php

return [

    'active_features' => [
         'change_team' => false,
         'change_series' => false,
         'change_user_settings' => false,
    ],

];

And I need a way for them to be able to toggle, say, 'change_team' to true or false every so often. I've searched around and haven't found anything at all to try. Does this kind of functionality exist at all?

In this situation you don't want to use a config file and instead you want to use plugin settings. The settings have a UI and save to the db, which does exactly what you want. The config files are meant to only be updated manually updating them.

http://buildwithcraft.com/docs/plugins/plugin-settings


Saving remote image to assets field in entry I'm working on importing entries from EE to Craft. I started with the craftimport plugin, and I am expanding it to do a bit more. One of the things I need is to save an image from a remote URL into an entry's assets field.

So far I've only managed to save it to disk, and then I can go into Craft admin and index the assets folder, and re-run the import, which will save the relation between the image and the entry using this:

$command = craft()->db->createCommand();
$imgRecord = $command
            ->select('id')
            ->from('assetfiles')
            ->where(array("AND", "filename='" . $images[0]['filename'] . "'", "folderId=2"))
            ->queryRow();

if ($imgRecord['id']) {
    $imgFieldRecord = FieldRecord::model()->findByPk($imgFieldId);
    $imgFieldModel = FieldModel::populateModel($imgFieldRecord);
    craft()->relations->saveRelations($imgFieldModel, $entryModel, array($imgRecord['id']));
}

So I'm wondering if it's possible to do this whole thing in one run instead of two? I guess the only thing the indexing does is look for images and store them in the database. But I can't seem to find anything in the documentation that tells me how to do it.

Your best bet to get the image in as an Asset in one go would be to use

$response = craft()->assets->insertFileByLocalPath($fileLocation, $fileName, $targetFolderId, AssetConflictResolution::KeepBoth);

$fileLocation would be the file's location on the disk
$fileName is the desired file name
$targetFolderId is the Assets folder, obviously. Look it up in craft_assetfolders table
The last argument is how to resolve any naming conflicts.

This will return an AssetOperationResponseModel object.

$fileId = $response->getDataItem('fileId');

This will get you the file Id. For an in-action example, see AssetsController::actionExpressUpload()

Note: This will copy the file to the location. This method is intended for importing a file into an Assets source from a different location, say, a temporary folder. It will probably work alright if the file is already in it's intended place, but I still feel like I need to warn you about this

You can also use this to import images to external sources, by the way.


Data cached in plugin controller via CacheService won't expire My cache won't expire. This is effectively my code:

    $template = (isset($params['template']) ? $params['template'].'?'.$config['pageParam'].'='.$pageParam : null);

    if(craft()->cache->get($template))
    {
        echo craft()->cache->get($template);
        craft()->end();
    }

    if(craft()->config->get('enableTemplateCaching'))
    {
        craft()->cache->set($template, $JsonValue, 'P1D');
    }

The cache saves just fine but when I forward the clock on my server a few days ahead and refresh the page it's still using the cached data. I've also tried actually waiting a few days in case it was using another clock but that didn't help either.

Is there something I'm missing? I figure Craft or the Yii Framework will take care of expiring the cache after the one day period set (P1D). I don't see any methods to check the date of the cache or anything where I could manually intervene.

For what it's worth I'm using theolampert's fork of the ElementAPI plugin which adds caching.

Looks like a bug in the plugin.

The 3rd $expire parameter when calling set states:

  The number of seconds in which the cached value will expire. 0 means never expire.

But it's passing in the PHP time format notation.  I'd suggest contacting the author of the plugin.


Can I call methods on an object represented by a string variable? I tried the attribute twig function for this but that did not work.

Essentially, what I'd like to achieve is the following:

{# This string variable is a name of the object #}
{% set myForm = 'form' %}
{# I'd like to call the 'errors' method on the 'form' object #}
{% set formErrors = myForm.errors %}

The problem with the above code is that the errors method will be called on the myForm object instead of the form object.

Is there any way to achieve what I'm trying to do here?

Twig's attribute function allows you to set the method as a string and not the object. The object has to be an actual object, even with that function.

{% set object = craft.entries.order('postdate').last() %}
{% set method = 'title' %}

{{ attribute(object, method) }}

The only workaround I can think of is to link your object-representing string to an actual object in your template. But this makes little sense as you probably wouldn't have set it as a string to begin with, hehe. Anyways:

{% if string == "craft.entries.order('postdate').last()" %}
    {% set object = craft.entries.order('postdate').last() %}
{% endif %}

{{ attribute(object, method) }}


How to render a template from within a module? I'm currently developing a module that contains a custom field and I'd like to create a template to be used in the getInputHtml method.

I try using the Craft::$app->view->renderTemplate method to render a template in the "resources" folder of my module, but Craft does not seem to find the template. How should I specify the path to the template from this module?

You need to include your template roots Enhancing a Craft CMS 3 Website with a Custom Module

public function __construct($id, $parent = null, array $config = [])
{
    Craft::setAlias('@modules/sitemodule', $this->getBasePath());
    $this->controllerNamespace = 'modules\sitemodule\controllers';

    // Base template directory
    Event::on(View::class, View::EVENT_REGISTER_CP_TEMPLATE_ROOTS, function (RegisterTemplateRootsEvent $e) {
        if (is_dir($baseDir = $this->getBasePath().DIRECTORY_SEPARATOR.'templates')) {
            $e->roots[$this->id] = $baseDir;
        }
    });

    // Set this as the global instance of this module class
    static::setInstance($this);

    parent::__construct($id, $parent, $config);
}


Fullscreen plugin in redactor I click on fullscreen button in redactor, However, an error in the console enter code here this.fullscreen.enable is not a function. And on enter click or paste text in new paragraph is added  ???
In general, there are not the best impressions of working with the editor.

Like Douglas suggested, you may not have the JS file you need so make sure you download the latest build and upload the files.


How to route to a controller action in Craft3? Before I get tagged as a duplicate I have already tried everything in the 'duplicate' issues on here to no avail so I'm posting my exact config to see what I'm doing wrong.

Here is my plugin code and my controller code

// My plugin and init funciton
use belniakmedia\sitedominjector\controllers\DefaultController;
class SiteDomInjector extends Plugin
{
    /**
     * @var SiteDomInjector
     */
    public static $plugin;

    /** @var array */
    public $controllerMap = [
        'default' => DefaultController::class,
    ];
    public function init()
    {
        parent::init();
        self::$plugin = $this;

        // Register our site routes
        Event::on(
            UrlManager::class,
            UrlManager::EVENT_REGISTER_SITE_URL_RULES,
            function (RegisterUrlRulesEvent $event) {
                $event->rules['echo'] = 'site-dom-injector/default/index';
            }
        );
    }
}

// My Controller
class DefaultController extends Controller
{
    protected $allowAnonymous = true;

    public function actionIndex()
    {
        $result = 'Welcome to the DefaultController actionIndex() method';
        return $result;
    }
}

I really don't know if that controller map is necessary or not but one of the posts on here said they got it to work setting that up, so thats what I did.

Here is a photo of my plugin's file structure for continuity:

I really have no idea why this isnt working but no matter what I do, when I try to browse to http://site.local/echo I get a 404 not found and the trace seems like its not even attempting to load the controller and is just looking for a matching template file... :(

Any ideas?

The problem ended up being something underlying in craft or yii2 that will not route the word "echo".

I changed out "echo" to "test" and it works fine. Even with both routes in, one does not and one does:

    // Register our site routes
    Event::on(
        UrlManager::class,
        UrlManager::EVENT_REGISTER_SITE_URL_RULES,
        function (RegisterUrlRulesEvent $event) {
            $event->rules['echo'] = 'site-dom-injector/default/index';
            $event->rules['test'] = 'site-dom-injector/default/index';
        }
    );


HTTP 503 – Service Unavailable – craft\web\ServiceUnavailableHttpException I have a problem with my page after upload on server. Currently a enabled devMode and while loading it shows

  HTTP 503 – Service Unavailable – craft\web\ServiceUnavailableHttpException

  whatmore:

  vendor/yiisoft/yii2/base/Application.php at line 386 – craft\web\Application::handleRequest(craft\web\Request)

web.log below:

  2018-07-19 07:11:06 [80.55.43.241][-][72baf4994c2e29ee1f32982349aec971][info][yii\db\Connection::open] Opening DB connection: mysql:host=localhost;dbname=my_database;port=3306;
  2018-07-19 07:11:06 [80.55.43.241][-][72baf4994c2e29ee1f32982349aec971][profile begin][yii\db\Connection::open] Opening DB connection: mysql:host=localhost;dbname=my_database;port=3306;
  2018-07-19 07:11:06 [80.55.43.241][-][72baf4994c2e29ee1f32982349aec971][profile end][yii\db\Connection::open] Opening DB connection: mysql:host=localhost;dbname=my_database;port=3306;
  2018-07-19 07:11:06 [80.55.43.241][-][72baf4994c2e29ee1f32982349aec971][error][craft\db\Connection::open] SQLSTATE[HY000] [2002] No such file or directory
  2018-07-19 07:11:06 [80.55.43.241][-][72baf4994c2e29ee1f32982349aec971][error][craft\db\Connection::open] SQLSTATE[HY000] [2002] No such file or directory
  2018-07-19 07:11:06 [80.55.43.241][-][72baf4994c2e29ee1f32982349aec971][info][yii\web\Session::open] Session started
  2018-07-19 07:11:06 [80.55.43.241][-][72baf4994c2e29ee1f32982349aec971][error][yii\web\HttpException:503] craft\web\ServiceUnavailableHttpException in /path/to/public_html/www/vendor/craftcms/cms/src/web/Application.php:507
  Stack trace:

  0 /home/cluster-sites/3/t/toolmach.co.uk/public_html/www/vendor/craftcms/cms/src/web/Application.php(184): craft\web\Application->_processInstallRequest(Object(craft\web\Request))

  1 /home/cluster-sites/3/t/toolmach.co.uk/public_html/www/vendor/yiisoft/yii2/base/Application.php(386): craft\web\Application->handleRequest(Object(craft\web\Request))

  2 /home/cluster-sites/3/t/toolmach.co.uk/public_html/www/web/index.php(21): yii\base\Application->run()

  3 {main}
  2018-07-19 07:11:07 [80.55.43.241][-][72baf4994c2e29ee1f32982349aec971][trace][yii\base\View::renderFile] Rendering view file: /path/to/public_html/www/vendor/yiisoft/yii2/views/errorHandler/exception.php
  2018-07-19 07:11:07 [80.55.43.241][-][72baf4994c2e29ee1f32982349aec971][trace][yii\base\View::renderFile] Rendering view file: /path/to/public_html/www/vendor/yiisoft/yii2/views/errorHandler/callStackItem.php
  2018-07-19 07:11:07 [80.55.43.241][-][72baf4994c2e29ee1f32982349aec971][trace][yii\base\View::renderFile] Rendering view file: /path/to/public_html/www/vendor/yiisoft/yii2/views/errorHandler/callStackItem.php
  2018-07-19 07:11:07 [80.55.43.241][-][72baf4994c2e29ee1f32982349aec971][trace][yii\base\View::renderFile] Rendering view file: /path/topublic_html/www/vendor/yiisoft/yii2/views/errorHandler/callStackItem.php
  2018-07-19 07:11:07 [80.55.43.241][-][72baf4994c2e29ee1f32982349aec971][trace][yii\base\View::renderFile] Rendering view file: /path/topublic_html/www/vendor/yiisoft/yii2/views/errorHandler/callStackItem.php
  2018-07-19 07:11:05 [80.55.43.241][-][72baf4994c2e29ee1f32982349aec971][info][application] $_GET = []

  $_POST = []

  $_FILES = []

This isn't a direct answer to your question, but the first place I'd look is your logs on your server. As an example, I'm running nginx on my server and the logs are located in /var/log/nginx/.


Difference between {% includeCssFile %} or including it with I go a simple question. I wanted to start with building my craft template from html and changed all css  and  tags to to equivalent {% includeCssFile %} or {% includeJsFile %}.

The page was working but my live preview was broken. It could not load the CSS, JS and other files. So I searched this forum and found out i should use {{ siteUrl }} on my links. I changed all back to   and now live preview is working.

So I'm wondering: why or when should we use this kind of include file tags?

The difference is that {% includeJsFile %} can be called in any template or template part and will add the script to the bottom of the page (as explained here).

So you could, for example, have a field that requires some JavaScript, say an image slider. You'll only need the JavaScript for that slider, not for the rest of the website, so in the template part where you set up the HTML for the slider, you also include the needed JS with {% includeJsFile %} and it will get added to the bottom of the page.

Where as with just including it in the head will load it on all pages.

It's the same for {% includeCss %}.


(Commerce) Multiple line items with the same purchasable ID? I'm using onPopulateLineItem in my plugin to dynamically set the price of products added to the cart based on user input on the front-end -

$lineItem = $event->params['lineItem'];

$size = craft()->request->getPost('size');
$colour = craft()->request->getPost('colour');
$finish = craft()->request->getPost('finish');

$options = array(
  'size' => $size,
  'colour' => $colour,
  'finish' => $finish
);

$lineItem->options = $options;
$lineItem->price = $dynamicPrice;

This is working fine, however, if the same product item is added to the cart but with different options (and therefor a different price) the existing line item is overwritten with the new values/price.

Is there a way I can create a new line item each time, rather than overwrite the existing one? Do I need to use a different event or create some kind of custom controller?

Thanks!

Commerce will by default combine line items that have the same hash value for the options (that is, the values of the items chosen options are run through md5 to get a hash - if the hash matches, the lineItems quantity is increased as the item is seen as the same item.

If you want line items with the same options to remain as separate line items, then you can simply add another unique option to the product as you add it to the cart (you don't need to display this of course).

<input type="hidden" name="options['whatevs']" value="somethingRandom">

Twig isn't actually ideal at generating random things I believe, I'd personally create a template variable in my Business Logic plugin that returns a random value, e.g. something like:

public function random(){
    srand(time());
    return rand(1,time());
}

You can e.g. call the current timestamp in twig but there's always a chance that might not end up as random I suppose?

<input type="hidden" name="options['time']" value="{{ date().timestamp }}">

(Calling twigs own random (https://twig.sensiolabs.org/doc/2.x/functions/random.html) - doesn't seem ideal as that's inclusive so you might see the edge values returned more than you'd like).


How to reference the current entry element in custom Control Panel templates? This might provide it's own answer, but I thought I would ask to be sure. How do you reference the current entry in custom fieldType or CP templates? I have tried {{ entry.id }}, {{ element.id }} but neither work. Do you need to explicitly set these variables in your getInputHTML() function?

I see in the craft '_entry.html' template that {{ entry.id }} is used for a hidden field. Since that reference is not available, I assume that template variables are scoped to the template and not inherited by other templates on the same page?

Through trial and error I finally discovered the current entry can be referenced in PHP as $this->element;, and the id and section via $this->element->id, $this->element->section respectively. So, I could add entry as a template variable, but I just assumed it would already be there.

public function getInputHtml($name, $value)
{
    $entry = $this->element;
    return craft()->templates->render('myPlugin/fieldtypes/MyField/input', array(
        'name'          => $name,
        'value'         => $value,
        'entry'         => $entry
    );
}

As you discovered, you can get the current element that a field type is getting applied to via $this->element. However you must keep in mind that that property will not always be set. So make sure that your PHP/template code is defensive about the possibility that there is no known element yet.

Another assumption to avoid is that the current element is going to be an entry. Craft lets you associate fields with any type of element - entries, users, assets, categories, tags, globals, and Matrix blocks, and even any custom element types that plugins may add. So $this->element->section should be avoided unless you know that $this->element is actually an EntryModel; otherwise that will give you a PHP error.


Project file changes causing `SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1' for key 'PRIMARY'` I switched over to use project file settings and now I occasionally get a constraint violation when trying to run the craft projectconfig/sync command.

I think this is a bug, because the

UPDATE `info` SET `id`=1, `version`='3.3.0.1', `schemaVersion`='3.3.3', `maintenance`=0, `config`=' ...`

statement seem to be missing a WHERE, which means it tries to set ALL rows in table info to the same values. For some reason, I end up having 2 rows in info where the one with id=2 is basically empty.

This is on version 3.3.0.1.

Invoking a DELETE FROM info WHERE id = 2; resolves the situation in my case, but it is a bit cumbersome that this happens.

As far as I know the craft_info table should only have one row.

This would mean that either:

You have something installed / configured wrongly somewhere causing it to insert a 2nd row into the table
Or it's actually a craft bug, I'd advise you to search through The CraftCMS Github Issues and check if there's any issue resembling yours, if not create an issue there so it gets solved in the next few updates.


How to pull entries with Date Created > start and < end? I'm building an export plugin in Craft 2 and the entries are saved by the front-end and are never enabled, so no Post Date.  I have a form with the forms.date selectors that sends a start and end date to my controller.  How can I filter on Date Created?  After and before only works on Post Date.

I have this for now:

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'contestEntries';
// Date Created >= start_date
// Date Created <= end_date
$criteria->status = null;
$entries = $criteria->find();

Thank you

Here is syntax you can use to search a date field between two dates.

$startDate = date('Y-m-d', strtotime($settings["start_date"]["date"]));
$endDate = date('Y-m-d', strtotime($settings["end_date"]["date"]));

$criteria->dateCreated = ['and','>= '.$startDate, '<= '.$endDate];


Feed me: set entrytype dynamically Can someone confirm that when importing entries with Feed-Me, the entrytype can NOT be set dynamically based on a field of the feed?

i don't think it is possible via GUI but you can do this via feed me events and a simple plugin.

because entrytype's fieldlayout and field mappings are different, in my solution, you should edit feed and update fieldmapping for each entry type, change the if condition of the code and run the feed again.

    Event::on(Process::class, Process::EVENT_STEP_BEFORE_ELEMENT_SAVE, function (FeedProcessEvent $event) {
        $entryTypeId=$event->feedData['entrytype'];
        if ($entryTypeId==1){
            $event->element->typeId=1;
        }
        //maybe, if field mapping for entrytype1 and entrytype2 are same
        elseif ($entryTypeId==2){
            $event->element->typeId=2;
        }
        else {
            //skip saving element for other entry types because they have different field mapping.
            $event->isValid=false;
        }
    });

about event->isValid


Should the timezone in general settings effect the output of $time = date("g:ia");? I am using the following in a plugin which I would expect to simply output the time of the server.

// get current time
$time = date("g:i a");
// outputs 9:36am

In a straight .php file this is correct - however, from within the plugin the time is an hour out - 8:36am. I imagine this might be to do with British Summer Time. However, in Crafts general settings I have set Timezone to UTC+1 (BST) - Europe/London

Yes, Craft calls date_default_timezone_set('UTC'); when initializing, so PHP will output all times in UTC by default.

If you want to output a time using the timezone that Craft has been set to in General Settings, you can do that with a DateTime object.

$now = new DateTime();
$time = $now->format('g:i a');


Order entries by custom date and time fields I have an events channel where each entry has three custom date/time fields:

startDate (Date Only)

startTime (Time Only)

endTime (Time Only)

I was originally using this code to set my entries, but it causes problems if they aren't all entered on the same day:

{% set allEntries = craft.entries.section('sparkSchedule').limit(null).orderBy('startDate asc').all() %}

I've seen answers from Craft 2 saying that i could use time(startTime) to sort by just the time portion of my startTime field:

{% set allEntries = craft.entries.section('sparkSchedule').limit(null).orderBy('startDate asc, time(startTime)').all() %}

but when I do that, i get this error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'startTime' in 'order clause'

Am I doing something wrong?

You'll want to change that startTime to field_startTime.

Anything in the orderBy gets passed directly onto SQL and Craft is smart enough to do the replacement for startDate behind the scenes, but columns in methods (like time()) or aggregate functions need to be manually prefixed.  This should work:

{% set allEntries = craft.entries.section('sparkSchedule').limit(null).orderBy('startDate asc, time(field_startTime)').all() %}


Use regex in replace filter any idea why this: %20AND%20foo%3A%22(.+?)%22 won't match this: %20AND%20foo%3A%22some random string of characters%22 in the Twig |replace filter?

If i do this:

{% set foo = '%20AND%20foo%3A%22some random string of characters%22' %}
{% set bar = '%20AND%20foo%3A%22(.+?)%22' %}
{{ foo |replace(bar, 'replaced') }}
{# OR THIS #}
{{ foo |replace((bar), 'replaced') }}

The result is foo. Nothing gets replaced. I'd expect the result to be the string "replaced". What am I doing wrong?

UPDATE: As of Craft v2.2, the replace filter now supports regex:

  The replace filter now supports regular expressions, by setting the first argument to a string that begins and ends with forward slashes, e.g. '/foo/'.

So this should work by adding forward slashes.

{% set bar = '/%20AND%20foo%3A%22(.+?)%22/' %}

I think this is particular to Craft and not native to the Twig replace filter.

I don't think the Twig replace filter will allow for regex matches.

According to this post, Twig only uses regular expressions with Comparisons.

But there are third-party plugins which might work:

Twig PCRE Filters
Low Regex


Does setting requireMatchingUserAgentForSession to false have any additional implications to be aware of? I recently ran into an issue that I was able to fix with what feels like a workaround – updating the config setting requireMatchingUserAgentForSession to false.

While I expect something changed on the website where I needed to do this, I'm not sure what would have changed and am curious if anybody with deeper knowledge of how user agents and sessions work could help explain what factors are at play here.

In my situation, members of the site were getting logged out shortly after they logged in and, while I could login to the control panel and navigate to several pages, each time I tried to access the Users tab, no users would display and I'd get logged out.  Each time this happened the corresponding item in the logs referenced a discrepancy between the user agent in the cookie and the current user agent.  The specific error message was:

  Tried to restore session from the the identity cookie, but the saved
  user agent (Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3)
  AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109
  Safari/537.36) does not match the current userAgent (Mozilla/5.0
  (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like
  Gecko) Chrome/48.0.2564.116 Safari/537.36).

The error outlines a discrepancy between Chrome/48.0.2564.109 in the cookie vs the current Chrome/48.0.2564.116.

What scenario creates a discrepancy between the User Agent in the cookie and the current User Agent? What variables can change that cause a previously working membership site, to require suppressing differences in these variables to work?  Does suppressing this required match and allowing for differences in the current User Agent and the session open up possibilities for other issues to arise?

The reason Craft stores the user agent string in the authentication cookie when logging in is to help prevent session/cookie hijacking.  If will validate that it is the same subsequent requests on the presumption if your cookie is hijacked, there's a significant chance that the browser that stole the cookie will have a different user agent string that the one the session was started with.

Granted, this isn't fool proof (user agent strings are easily spoofed) and some browsers store their version number (like you discovered) in the user agent string as well.  This is all well-and-good until your browser decides to auto-update, forcing the string to change and then auto-logging you out of Craft, which looks like what you're seeing.


How can I populate a dropdown via table field type using the default values? In the CP I have a table field called colors. I have two columns, "Label" and "Value".

I have populated the table with two default values "Red" and "Blue" (attached).

This table will ultimately populate a dropdown on the front end. Label being the label, and value being the value.

When I edit the entry that I have assigned the colors field to, the default values do not show. I can only choose "Add a row". I do want to be able to add/remove rows like this, but I'd like to have "Red" and "Blue" be there by default.

On the template level I create the dropdown like this:

{% if entry.colors|length %}
<select id="colors" name="colors">
    <option value="">Select</option>
    {% for color in entry.colors %}
        <option value="{{ color.value }}">{{ color.label }}</option>
    {% endfor %}
</select>
{% endif %}

The drop down does not show until I enter a value in the entry. I'm not sure what I'm doing wrong so that the drop down will pull in the default values by...default.

You will only get the defaults for new entries.


Filtering and sorting lists in a plugin Whats the recommended way to have javascript based filtering and sort table views in a plugin tab?

Is is possible to use garnish to do that or should we be looking at external libraries like:

http://www.datatables.net/

I don't believe that there is a recommended way to do this, so I'll attempt to answer this question as best I can.

By using an element type, you will be able to use the element index layout for free, with very little setup. That will give you access to native sorting and searching (filtering), along with a bunch of other things such as grouping, statuses, table and thumbnail views, etc. Creating your element type template is as simple as including the following 3 lines:

{% extends "_layouts/elementindex" %}
{% set title = "ElementName"|t %}
{% set elementType = 'PluginName_ElementName' %}

There is not way that I know of to natively allow sorting of a table without using an element type and it doesn't look like Garnish offers this functionality.

So I guess the only way at present to make this work with JavaScript is to use an external library such as tablesorter or as you mentioned DataTables.


How can I add "and" between multiple categories assigned to an entry? I have some entries that have more than one category assigned to them (under the same category group).  For example, Entry X might be assigned to Category A and Category D.   How do I get it to print "Category A **and** Category B" instead of Category A Category B"?

Loop through the categories of the entry, add and if it's not the last loop index, like so:

{% for category in  entry.categoryFieldHandle %}
 {{category.title}} {{ loop.last ? '': 'and '}}
{% endfor %}


Adding a mailing list subscribe to contact form Is there an existing plugin or a built-in way of adding an "add me to mailing list" button to a contact form? Not just that it gets stored in the database as a lightswitch, but so it actually subscribes them (or at least sends them a sign-up confirmation email)?

There isn't a native way to to do that... it would have to be done with a plugin.

I'm not sure if there is an existing one, but Straight Up Craft currently has the most up-to-date list of available Craft plugins, so that would be a good starting point.


Variable 'foo' does not exist in template I've uploaded my site to the live server and i'm getting

Template Error

Variable "heading" does not exist

On a couple of pages. This is only happening to 2 sections, the rest are all fine.

and it then goes onto identify the template and template var that it claims is missing.

But, there is no db or file difference to the local or dev sites!

I've cleared caches, double checked permissions, changed php versions to no avail. Any ideas?

Update, i had devmode set to true, and have set it to false now, but, now the page renders, it does not output any text content from the cms. Just an image. Odd.

Well, oddly, the answer was instead of {{ heading }} i needed to do {{ entry.heading }}

Very odd.


Transfer licenses into another Craft ID account I could only transfer licenses that were not yet assigned to any other Craft ID account. But how can I transfer the licenses, which are assigned with my other Craft ID account?

You will have to release the license in your Craft ID account:
https://id.craftcms.com/account/licenses/cms

After that you will be able to claim the license in your other Craft ID account:
https://id.craftcms.com/account/licenses/claim


Submit via ajax to Guest Entries plugin I'm trying to submit entry data via AJAX (using Guest Entries plugin) following what's written in a similar question, however even though I am not sending the data in JSON format, the data does not seem to want to save and keeps returning a "cannot be blank error" for every field submitted.

{"errors":{"title":["Title cannot be blank."],"add01e":["Email cannot be blank."],"firstName":["First Name cannot be blank."],"lastName":["Last Name cannot be blank."]}}

These are, in reality, are being submitted as can be seen below. What's strange is that the sectionId and action are being processed for the server to respond with the latter list of errors.

Sent Form Data Source:

action=guestEntries%2FsaveEntry&sectionId=14&firstName=asdsa&lastName=dsad&add01e=asd%40sd.com&companyName=asd&redirectUrl=%2Fcontent%2Fdownloads%2Fproducts%2Fstrokepad%2F6pm-strokepad-brochure-a4_web_300115.pdf&title=Download+Request

Sent Form Data Parsed:

action:guestEntries/saveEntry
sectionId:14
firstName:asdsa
lastName:dsad
add01e:asd@sd.com
companyName:asd
redirectUrl:/content/downloads/products/strokepad/6pm-strokepad-brochure-a4_web_300115.pdf
title:Download Request

Other details related to the request:

Request URL:http://craft.dev/
Request Method:POST
Status Code:200 OK

Content-Type:application/x-www-form-urlencoded; charset=UTF-8

JS performing the ajax request:

var formData = $form.serializeArray();
formData.push({name:'title',value:'Download Request'});
$.post('/', formData , function(response) {
    if (response.success) {
      //On Submit Success
    }else{
      alert('An error occurred. Please try again.');
    }
});

Any idea what I might be doing wrong?

Thanks in advance!

Ok found the solution to this.

All input fields must have the following format fields[handle] - i was just using the handle!

Example:

<input name="fields[firstName]" id="firstName" type="text" placeholder="First name *">


Templates and structures I have decided to use Structures as a section type for a section of our site. Can anyone point me to some good documentation for this?

In particular I have set up a structure and I have an _entry.html and an index.html file in a directory for the structure section. When I call the url domain.com/mystructure I am served a 404 error page instead of the index.html page.

If you haven't seen it already there is some good Docs on the Craft site on sections and how to use them.

Without seeing your Structure settings it is hard to pin-point exactly what the issue is here, but creating a Structure and adding your templates to it is a very easy procedure. I have attached a screenshot of a Structure for a project I am currently working on, so you can reference in case you have made a mistake somewhere.

So in my templates I have created a folder called services, and in there I have my index.twig and _entry.twig files. Try matching your Structure settings with the screenshot and see if that fixes your problems.


my vendor/craftcms/cms folder delete automatically after every update or install I was on version 3.1.22. As usual, I wanted to install the update on Craft CMS 3.1.23.
So I clicked Install and got this error:

  Status: Error

But that was not all ... My complete vendor/craftcms/cms folder has been deleted. The solution to get back to the CP and the frontend, was to manually upload 3.1.22 back to the folder. When I started the update again - same error. In the while, I have manually updated to 3.1.24. However, I can no longer update plugins or install new ones. The CMS folder is deleted every time.

Does anyone have a similar problem or idea how to solve this? Thanks!

I had a similar issue yesterday.

When running composer install from my linux (Homestead box), via the command line, a stack of weird errors flew by indicating a "problem with the zip file".

Then craft died. All the vendor/craftcms files were created but empty!

Only way round it, for me, was to run the composer install from windows instead.


NotificationEmailEvents class not found I'm trying to follow along with the guide on creating custom notification events in a plugin found here: https://sprout.barrelstrengthdesign.com/docs/email/custom-notification-events.html#register-event

I used their example Manual class as my notification and now I'm trying to register it, however, I get an error of:

Class barrelstrength\sproutbase\app\email\services\NotificationEmailEvents' not found.

I checked and made sure that the sprout email is installed and enabled and also my plugin is installed and enabled.

Below is what is in my main plugin file:

namespace mycompany\plugin;

use myname\company\notifications\Manual as PluginManualNotification;

use barrelstrength\sproutbase\app\email\services\NotificationEmailEvents;
use barrelstrength\sproutbase\app\email\events\NotificationEmailEvent;

use Craft;
use craft\base\Plugin;
use craft\services\Plugins;
use craft\events\PluginEvent;

use yii\base\Event;

class MyPlugin extends Plugin
{
    public static $plugin;
    public $schemaVersion = '1.0.0';

    public function init()
    {
        parent::init();
        self::$plugin = $this;

        Event::on(
            Plugins::class,
            Plugins::EVENT_AFTER_INSTALL_PLUGIN,
            function (PluginEvent $event) {
                if ($event->plugin === $this) {
                    // We were just installed.
                }
            }
        );

        Event::on(
            NotificationEmailEvents::class,
            NotificationEmailEvents::EVENT_REGISTER_EMAIL_EVENT_TYPES,
            function (NotificationEmailEvent $event) {
                $event->events[] = PluginManualNotification::class;
            }
        );
    }

    /* Create settings modal and other unrelated stuff */
}

The docs at the time of the question reference an old classname in the C3 example, the two Notification Email related classes in your code are now in a module named sprout-base-email:

NEW
use barrelstrength\sproutbaseemail\services\NotificationEmailEvents;
use barrelstrength\sproutbaseemail\base\NotificationEvent;

OLD
use barrelstrength\sproutbase\app\email\services\NotificationEmailEvents;
use barrelstrength\sproutbase\app\email\events\NotificationEmailEvent;


Change password on user profile (customer account in Craft Commerce) I have a customers area as part of the Craft Commerce site I am working on. Ideally I want the user to be able to update their password from their customer profile screen. I have it working and validating for First Name and Surname. I have made the email address a disabled field so this cannot be changed (as email is used t login).

However, I am having difficulty getting validation for the password fields. If I enter the old password correctly and a new password it does work and updates the password. However, I want some feedback/error trapping on the old password box to ensure the old password was correct and to offer some feedback if the passwords cannot be updated for whatever reason.

Is this something we would need to write to validate the old password, or is this baked into Craft?

Anyone able to point me in the right direction on this?

Commerce just relies on existing Craft functionality for this and if you look at UsersController->saveUser, you can see that if the existing password is incorrect, then the error will be added to the UserModel's currentPassword property.

So something like this should work:

    {% for error in user.getErrors('currentPassword') %}

{{ error }}

    {% endfor %}


How do I fix PHP Notice - Undefined index: releaseDate? I'm getting this error:

Undefined index: releaseDate in craft/app/etc/behaviors/AppBehavior.php(500)

Line 500: $row['releaseDate'] = DateTime::createFromString($row['releaseDate'], null, false);

Is there anything I can do to fix this?

I've run into this issue myself with Craft version: 2.6.2962.

The line in question is expecting a column from the database called "releaseDate".
In my case, that column no longer exists. It might have gotten dropped or lost with one of the updates, I am not sure.

A short-term solution would be to edit that line of code and pass in some different value.

In my case, I changed the line to:

$row['releaseDate'] = DateTime::createFromString($row['dateUpdated'], null, false);

And to clarify, looking at the changelog, it seems they are in the process of tweaking the craft()->releaseDate() function call.

Update 03/06/2017:
It appears that my code-base was outdated with the version in my database. I updated to the latest version of craft and that line that I edited above is now gone.

My question to you: Is your craft version up to date?


Pulling categorized entries in a category loop I am trying to pull channel entries and display them using a loop. These entries would then be organized by the category they are assigned to based on a categoryfield a user selects when creating the entry. Below is the code I am beginning with.

{% set category = entry.myCategoriesField.first() %}
{% if category %}
 {% for car in craft.entries.section('category')%}
  **Might need a set option here for entries??**

  {{car.Title}}
  {{car.carDescription}}

 {%endfor%}
{% endif %}

Should look like:

Car

Prius: {{Description}}

Truck

Ram {{Description}}
Silverado{{Description}}

SUV

Suburban {{Description}}
Escape {{Description}}

Any thoughts or direction would be helpful.

I have looked into the following code but don't think it would work the way I want to.

{% set category = entry.myCategoriesField.first() %}
{% if category %}
    ...
{% endif %}

Have part of the solution which is to use:

{% set categories = entry.categoriesFieldHandle %}
{% if categories | length %}

Some great categories

{% nav category in categories %}
    {%for entry%}
    {%endfor%}

{% endnav %}
{% endif %}

Just now need to find out how to add the Category Title in and work on separating the entries out.


Check for errors (any) on guest entry form (Craft 3) I have a guest entry form that's working fine. I'm using Craft-supplied code:

{% macro errorList(errors) %}
  {% if errors %}
    {% for error in errors %}
      {{ error }}{% if not loop.last %}, {% endif %}
    {% endfor %}
  {% endif %}
{% endmacro %}

And it works fine - field by field:

{% if entry is defined %}

{{ errorList(entry.getErrors('title')) }}

{% endif %}

But I can't figure out how to check if there are any errors (and error in any field) so I can display a notification at the top of the page: "There were some problems with your submission".

{% if errorList(entry.getErrors())|length }}

doesn't work.

You can use this

{% if entry.hasErrors() %}
    Render a message here
{% endif %}


Is there a limit to outputting entries in 'free' version of Craft CMS? I am outputting all my entries and it seems that on the front end, it isn't displaying entries from N to Z. I see those entries in the backend. The entries on the front end:

http://www.colorcomputergames.com/games

The template conditional doesn't have any limits on N to Z or the number of entries to show. The entries are enabled.

Is this due to using the free version of Craft CMS or some other setting?

My template code is:

{% extends "_layout" %}
{% set title = "Games" %}
{% set entries = craft.entries.section('games').order('title') %}
{% block content %}

    {% for entry in entries %}

            {{ entry.title }} ... {% set publishers = entry.GamesPublisher %}{% for publisher in publishers %}{{ publisher.title }} {% endfor %}{% if entry.GamesGenre is not empty %}{% for category in entry.GamesGenre %}{{ category.title }}{% endfor %}{% endif %}{% if entry.GamesReleaseYear is not empty %} {{ entry.GamesReleaseYear.format('Y') }}{% endif %}

    {% endfor %}

{% endblock %}

Craft will limit the number of elements returned by default to 100, so if you're expecting to get > 100 entries, that's probably what you're running into.

To grab all entries, use:

{% set entries = craft.entries.section('games').order('title').limit(null) %}

Note that this default limit of 100 no longer exists in Craft 3.


Problem upgrading Craft CMS? When trying to upgrade Craft CMS automatically we get a message relative to the SSL certificate of the CDN being incorrect, though it works fine on a local machine.

  Craft was unable to install this update :(

  [curl] 51: SSL: no alternative certificate subject name matches target
  host name 'download.craftcdn.com' [url]
  https://download.craftcdn.com/craft/2.6/2.6.2967/Patch/2.6.2962/41d682834df8c739ead7a1abab6a4571.zip

Anybody else getting this?

That cURL 51 error usually means that your server doesn't understand the SNI SSL certificate we have installed at https://craftcms.com and https://craftcdn.com.

Technically there are 3 things a server needs to recognize SNI SSL certs:

Using a version of cURL that supports it, at least 7.18.1 (8 years old: https://curl.haxx.se/changes.html)
Using a version of cURL compiled against a library that supports SNI, e.g. OpenSSL 0.9.8j (depending on the compilation options some older versions. 7 years old: https://www.openssl.org/news/changelog.html)
Using TLS 1.0 at least (not SSLv3)

Once the box Craft is on meets those requirements, it should start working.


Get the author of current entry version? How would I go about to get the author from the current version / revision of the entry I'm on? Im trying to get "last updated by" in frontend, but authorId on the entry seems to be the original author, not the last that edited it.

You have to write a template variable that makes getVersionsByEntryId() available in Twig.

public function getVersionsByEntryId($entryId, $localeId, $limit = 1, $includeCurrent = true)
{
    return craft()->entryRevisions->getVersionsByEntryId($entryId, $localeId, $limit, $includeCurrent);
}

You can now access an entry’s versions and get the current version’s creator like so.

{% set versions = craft.businessLogic.getVersionsByEntryId(entry.id, entry.locale) %}
{% set author = versions|length ? versions[0].creator : entry.author %}

{{ author.fullName }}


Error after downgrading from Pro to Personal We developed a website under the trail Pro license. But now on the production server, we downgraded Craft to Personal. Since then we can't save entries and get a warning about it.

The logfile gives the next errors:

2016-12-07 15:23:53

Level   error
Category    exception.Craft\HttpException.404
Message Craft\HttpException in /removed-path-for-sec/craft/app/controllers/TemplatesController.php:59
2016-12-07 15:23:47

Level   error
Category    application
Message CDbConnection failed to open the DB connection: SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: NO)

Upgrading to Pro solves the problem again. Could do that of course, but I'm wondering if there is an other solution :)

I was only able to answer this because the OP sent a support ticket to and was able to look at their database. :)

When the site was setup in Craft Pro trial mode, the content was built out with multiple locales and those locales were enabled for the sections.

Craft Personal only allows for 1 locale, so when you try to save an entry in a section that was originally setup for multiple locales under Craft Pro, you get an pretty generic "can't save entry" message.

If you go back to Craft Pro and remove the other 2 non-primary locales, the Craft Personal entry saving will work again.


Asset (image) public URL does not work I wanted to include some uploaded assets (images) in an entry. The .url property in twig outputs the proper URL, in my case:

  http://localhost/craftcms/web/image/photo-2017-04-02-16-20-53-1.jpg

However, that link is broken. Following it leads to a 404 error page:

  Template not found: image/photo-2017-04-02-16-20-53-1.jpg

Viewing it in the admin panel preview also displays a broken image sign.

If I disable the Public URL switch in the asset settings, the image display fine in the admin panel, but obviously I cannot use them in public pages.

I wasn't able to find a working fix for this. I tried the multiple-environment config solution from these forums just in case, but it did not help me.

Update: here is a screenshot of my Assets volume settings:

The issue is that your Asset Volume URL is @web/image but your Asset Volume path is @webroot/assets/art

That means that Craft will look for the images on disk (to do transforms, etc.) in web/assets/art but it will generate URLs for frontend requests that point to http://example.com/image -- where presumably nothing exists.

These should probably be:

URL: @web/assets/art
Path: @webroot/assets/art

...assuming that the web/assets/art/ directory is where these images live.


Assetconflict after changing general.php I've made a matrix field on one of my templates. After adding alot of content, and then trying to delete it, I get this message:

  include(/home/blabla/bla/craft/app/enums/AssetConflictResolution.php): failed to open stream: No such file or directory

The reason might be that I changed my basepath in general.php / staging issues. Any idea, anyone?

If it were related to basePath, then you'd most likely be getting other errors as well.

This one sounds like Craft simply can't autoload the file it's looking for.  I'd re-upload your craft/app folder to make sure all of the files got transferred up properly and aren't corrupted.


Empty page instead of 404 error when url contains channel slug I have a website where my client can create entries in a couple of different channels.

Lets take a "news" channel. The url would be: "example.com/news/nameofpage"

Whenever a wrong url is entered manually behind "example.com/news/" (or maybe a wrong filled in link) it won't go to the 404 page but just enters the channel's template and display's an empty page. For everything else the 404 error works but whenever a channels slug is in the url as a first segment it only gives an empty template.

EDIT:

I figured out it happens all the time whenever there is a second segment in the url

As Brad pointed out in the comments on my question I had to take a look in the custom route's defined in the Craft CP. My client tried to make a custom route which looked like this:

This caused for every url containing one "/" to use that template that unfortunately actually was a template that's why it wouldn't give a 404.

Original Comment:

Maybe an .htaccess rewrite rule interfering? Do you have any custom routes defined (in the Craft CP or in config/routes.php)? – Brad Bell


500 Error after Dreamhost server upgrade Dreamhost upgraded my VPS overnight and I immediately got a 500 error. The site currently works on another Dreamhost VPS (the original below) and an Arcustech server.
After checking the error logs I'm receiving this error:
AH01215: php73.cgi: unable to extent pixel cache `No such file or directory' @ fatal/cache.c/CacheSignalHandler/3626.: /dh/cgi-system/php73.cgi

The server was upgraded from:
Distributor ID: Ubuntu
Description:    Ubuntu 14.04.5 LTS
Release:    14.04
Codename:   trusty

to:
Distributor ID: Debian
Description:    Debian GNU/Linux 9.12 (stretch)
Release:    9.12
Codename:   stretch

I've done the following to try to resolve it

Deleted composer.lock & vendor/ and reinstalled everything.
Started a fresh directory and change the site to run out of that directory
restarted the MySql VPS, and VPS
Deleted mysqlVPS and VPS, the ordered a fresh build of both, reinstalling node, composer, etc.and rebuilding the site there

Dreamhost was ...uh...less than helpful on the matter.
Has anyone ever seen this problem?

Dreamhost was ...uh...less than helpful on the matter.

That's always been my experience with them.
Best I can tell (from https://github.com/the-paperless-project/paperless/issues/98 which has a similar error message) that error is coming from Imagick.
Whether it's a bug in Imagick (possible) or Dreamhost has misconfigured it on the VPS (more likely), it's hard to say, but either way, they should be looking into it.


Is it possible to install Craft on a cPanel temp user URL? When you create an account in cpanel you can use a URL to access it like http://ip/%7Eusername/, which is basically http://ip/~username/. Since the client is not ready to take down their old site and we are moving hosts, can Craft run on a URL with the ~username or %7E in the URL? They do not have a dedicated IP unfortunately. Thanks in advance.

I know the license will be needed, but can we change the URL to the real one when ready to go LIVE?

http://buildwithcraft.com/docs/multi-environment-configs

'example.com' => array(...

'should' work with an address like:

'123.45.67.89/%7eusername' => array(...

You might also try:

'123.45.67.89/~username' => array(...

Although using a proper domain name as in my comment above would be better.

Good luck. :)


Ignore 'action' querystring parameter Is there a way to ignore part of a querystring if it contains the parameter "action"?
We have a 3rd party site which returns to one of our sites and they append "&action=something" to the querystring. The 3rd party site are not able to remove this parameter, so when the user gets returned to our site they're greeted with a 404 page - the Craft docs suggest 'action' is used to determin an action controller to use, which in this case there is not one set.
My 'hack' of an idea would be to detect the parameter in a template, remove that parameter, then go to the url without the 'action' parameter set. This would add more page requests, which would be annoying for a user I can imagine.

I think we need more information to be able to consider possible solutions. I personally wouldn't do anything in Craft, rewriting this URL before it hits the application would be cleaner. I don't know if it's possible to configure the 'action' parameter name in Craft so let's assume not.
Are the referring URLs always the same? In other words, is the visitor always returned to the same URL on your site (which contains &action=something)? If so, a fairly simple Apache/nginx rewrite URL could be written to remove the parameter from the request.
If not, it may still be achievable with a rewrite rule if you're willing to trust the HTTP_REFERER variable.


Query for multiple date ranges on a date field I'm able to successfully query a date field for a date range using this syntax:
{% set entries = entries.startsOn(['and', '>= '~firstDay, '< '~ lastDay]) %}

What I would like to do however is query that field for multiple date ranges at once with an or operator.
I can do this with other fields but the date range already using an and operator complicates matters so I can't do the same.
{% set data = data|merge(['or']) %}
{% for item in items %}
     {% set data = data|merge(['*'~item~'*']) %}
{% endfor %}

Any suggestions gratefully received!

You can use two queries, each for each range, and then merge them like this:
{% set firstRange = craft.entries({fieldHandle: ['and', '>= '~date1FirstDay, '< '~ date1LastDay]}) %}
{% set secondRange = craft.entries({fieldHandle: ['and', '>= '~date2FirstDay, '< '~ date2LastDay]}) %}

{% set entries = firstRange |merge(secondRange) %}

This is the way to do it. Also you should query for the ids, and then merge those, and then query by id.
I hope this will help.


Import CSV with FeedMe - multiple categories I'm attempting to use FeedMe to import a CSV list of entries exported from Google Sheets. I have a column labeled "Categories" and an entry with category1,category2 as the value. I set up the feedMe job pointing to the CSV and the categories field to point to this column. However it is not importing/creating two categories (the expected behavior)rather it is just creating one category  with the name "category1,category2" -- am I doing something wrong as far as how to list out multiple categories in CSV? Can Feedme handle a comma separated list like this?
If I convert the sheet to a json, it produces: "Categories": "Category1, Category2" which does not work either - however if I edit the json to be "Categories": ["Category1", "Category2"] that works - but manually editing it is not really an option on my final spreadsheet as it will have over a 1000 entries.
If there's an easy way to convert the sheet/csv to correct Json I'd be open to that too.
Any help would be appreciated.

You can do this with CSV by setting a dataDelimiter in a config/feed-me.php files (see docs).
If you set the dataDelimiter to be | for example, then your CSV could be:
"title", "Categories"
"Some title", "Category1|Category2"

Doing this should let you import multiple categories from CSV.


How to handle custom text on a channel index page? I'm setting up a site with several channels, and the design requires an introductory paragraph at the top of each channel's index page (ie. before the list of entries) - essentially a post that corresponds to the channel's index page.

As I understand it, there's only a template but no entry corresponding to the index of a channel, so I'm wondering how best to handle this in Craft. I definitely don't want it hard-coded in the template, and ideally it should be somewhere reasonably intuitive for site admins to find and edit.

It feels like it should be straightforward to implement, but I just can't quite think how to do it. Any suggestions would be much appreciated!

I'd recommend to either give each channel's index page a dedicated single section or you configure a structure section to contain them all. An advantage of using a structure over separate singles is that you can generate the site's main navigation from it. And you can add a hierarchy to it.

The structure settings in the CP:

URL for Top-Level Entries:
{slug}

URL for Nested Entries:
{parent.uri}/{slug}

You probably want to give your index pages individual templates. To do this just add multiple entry types to your structure and relate each entry type with a template as described in the FAQs.


Craft can't connect to the database (using ec2) I'm trying to set up a Craft based site with ec2 and it won't connect with the info in db.php.

I've reinstalled the Craft files and also run all .phps through http://phpcodechecker.com to check for errors and nothing. Logs all check out to be in working order. And I've followed every step exactly with this tutorial: https://solspace.com/blog/spinning-up-a-craft-cms-development-site-on-amazon-ec2

Here's what my db.php file looks like:

return array(

    // The database server name or IP address. Usually this is 'localhost' or '127.0.0.1'.
    'server' => 'localhost',

    // The name of the database to select.
    'database' => 'Craft',

    // The database username to connect with.
    'user' => 'root',

    // The database password to connect with.
    'password' => '*******',

    // The prefix to use when naming tables. This can be no more than 5 characters.
    'tablePrefix' => "‘craft'",
);

I also checked .htaccess files.

So a couple of things:

It's probably not a great idea to connect as root -- it'd be better to create a mysql user that has access only to that db.
Make sure that the db you're connecting to is indeed named Craft (case may count here, I'm not sure)
The table_prefix looks wrong to me; probably it should be just: 'tablePrefix' => 'craft',

You also might consider checking out Multi-Environment Config for Craft CMS for multi-environment configs for Craft.


In Craft Commerce, is it possible to show a more meaningful error when the customer tries to add more of a product than is in stock to the cart Currently, if a customer attempts to add a greater quantity of a product to the cart than is in stock, an "Unable to update cart" flash message in shown.  e.g. there are 3 in stock and the customer tries to add 4 to their cart.
Is there any way to change what that error says? As obviously a customer isn't going to know what that means.
Thanks!

If you want to modify the error message, the way to do is not to use the craft.app.session.getFlash('error') value but use the cart.errors instead. Each of the errors has a unique key for specific error then you can add a condition on what message to display. It would something this.
{% if cart.errors|length %}

            {% for attribute, errors in cart.errors %}
               {% if attribute == "lineItems.0.qty" %}
                    {% for key, error in errors %}

Product is not available

                    {% endfor %}
                {% else %}
                    {% for key, error in errors %}

{{ attribute }}: {{ error }}

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

{% endif %}

You could also modify the Unable to cart message by adding this to the update cart form
E.g.
{{ hiddenInput('failMessage', 'Error adding cart.'|hash) }}


How to display data in field type with dropdown multi select checkbox? I'm able to get data using API but when I use checkboxField then it only display the blank checkbox without value. In Model,

    if($result){
        if (isset($result->error)) die($result->error_message);
        //convert json data to array
        $arr = json_decode($result, true);

        //Get project array from API
        $json = $arr['projects'];

        foreach ($json as $i => $v){

            return array_merge(parent::defineAttributes(), array(
                'someField'     => array(AttributeType::String, 'default' => $v['name']),
            ));
        }

And my template,

{% import "_includes/forms" as forms %}

{{ forms.checkboxField({
id: id ~ 'someField',
class:'nicetext',
name: name ~ '[someField]',
value: values.someField,
checked: value,
errors: values.getErrors('someField'),
required: false,}) }}

Need some help. TIA!

A checkbox field is just a checkbox, usually checkboxes don't have several values beside true/false or checked/unchecked, Are you sure you don't want to use a select or multiselect

{{ forms.selectField({
    label: "Some Label"|t,
    id: id ~ 'someField',
    name: name ~ '[someField]',
    options: options, //<-- array [label => X, value => y]
    value: values.someField // <-- not sure what this should be.. usually you want to pass an id
}) }}

However - your PHP actually doesn't make much sense. Not sure what your goal is with that code


Calling a plugin function after an entry is deleted? Is there a way to call a custom function after an entry is deleted successfully?

If there isn't, is there a record of the deleted record stored anywhere?

Currently, I am thinking of editing the actionPerformAction in elementIndexController, but I don't want to edit the application files, so if there is another method I would prefer that.

You can create a simple plugin that listens to the onDeleteEntry event.

There is an entry parameter passed into that event that is the EntryModel object that represents the entry that was just deleted.


How to display an entry on frontend with status disabled if admin is logged in? Something like this?

{% if craft.session.isLoggedIn %}
    {% set slug = craft.request.lastSegment %}
    {% set entry = craft.entries.slug(slug).status(null).first %}
{% endif %}

{{ entry.title }}

But I get error page not found.

If you're specifically checking for the admin, then it's more like:

{% if currentUser.admin %}
    {% set slug = craft.request.lastSegment %}
    {% set entry = craft.entries.slug(slug).status(null).first %}

    {{ entry.title }}
{% endif %}

If you're getting a 404, then it's some other routing issues that is occurring.


JQuery $.ajax ":success" form logic with Plugin Controller? I'm working on a simple plugin to facilitate front-end, anonymous lead generation forms submitted to Salesforce via cURL to it's Web-to-Lead servlet. The logic and data transfer are working (debug showing positive receipt of the query from the servlet), but no matter what the :success function on the $.ajax call isn't triggered.

I'm getting a 200 OK back from the cURL, so my assumption is that the :error function is being triggered because the result isn't properly formatted JSON. I'm calling the returnJson function from the baseController, however all I can see in the response object is "responseText" with the raw HTML of the servlet response.

Controller PHP

protected $allowAnonymous = array('actionPostLead');

public function actionPostLead()
{
    $this->requireAjaxRequest();

    // Initialize the $kv array and query var for later use
    $kv = array();
    $query_string = '';

    //If there are POST variables
    if ($_POST) {

        // For each POST variable as $name_of_input_field =&amp;gt; $value_of_input_field
        foreach ($_POST as $key => $value) {

            // Set array element for each POST variable (ie. first_name=Arsham)
            $kv[] = stripslashes($key).'='.stripslashes($value);
        }

        // Create a query string with join function separted by &amp;amp;
        $query_string = join('&', $kv);
    }

    // Check to see if cURL is installed ...
    if (!function_exists('curl_init')) {
        die('Sorry cURL is not installed!');
    }

    // The original form action URL from Step 2 :)
    $url = 'https://webto.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8';

    // Open cURL connection
    $ch = curl_init();

    // Set the url, number of POST vars, POST data
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, count($kv));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);

    // Execute SalesForce web to lead PHP cURL
    $result = curl_exec($ch);

    // close cURL connection
    curl_close($ch);

    if ($result) {
        $this->returnJson(array('success' => true));
    } else {
        $this->returnErrorJson($e->getMessage());
    }
}

Javascript

$.ajax({
    type: 'POST',
    url: '/',
    data: data,
    dataType: 'json',
    success: function(response) {

        formBlock.removeClass('submitting');
        var successMessage = $('.formBlock.on').data('success-message');
        showFormSuccessBanner(successMessage);
        hideForm(id);
    },
    error: function(err) {
        console.log("Error");
        console.log(err);

        formBlock.removeClass('submitting');
    }
});

I think I'm close, but I've been digging for several hours and can't figure out what I'm doing wrong with the response.

The issue was that curl was, by default, returning the result of the http request to the WebToLead servlet directly, rather than only storing it as $result. This raw HTML response was super-ceding the returnJson() response, resulting in an error in jQuery's ajax function.

To force PHP curl to echo the result rather than return it, you need to set a curl option for CURLOPT_RETURNTRANSFER to true. Revised as such:

// Set the url, number of POST vars, POST data
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE  );
curl_setopt($ch, CURLOPT_POST, count($kv));
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);

This returns just the JSON response from the function in Craft's baseController, and therefore a successful response to jQuery.


Commerce custom field output I have a custom field that allows customers to order a sample from a list of all products. It also allows a custom value to be entered for a custom color. I conditionally show/hide the fields with javascript and all the options are available on one product type. This works great except for one thing. On the admin emails it shows every option even if nothing was filled out. I have the labels set to only show if there is a value but they still output.

Here is the product type code:

    <select name="purchasableId">
        <option>Please Select Sample Type</option>
        {% for purchasable in product.variants %}
        <option {% if purchasable.stock <= 0 and purchasable.hasUnlimitedStock == false %}disabled {% endif %}
                value="{{ purchasable.id }}">{{ purchasable.description }} {{ purchasable.price|commerceCurrency(cart.currency) }}</option>
        {% endfor %}
    </select>

    {# pattern #}
    <select name="options[pattern3a]">
      <option value="">Select Wallpaper Sample 1</option>
      {% for product in craft.products.type('wallpaper').all() %}
      <option value="Sample - {{ product.title }}">{{ product.title }} </option>
      {% endfor %}
    </select>
   <select name="options[pattern3b]">
      <option value="">Select Wallpaper Sample 1</option>
      {% for product in craft.products.type('wallpaper').all() %}
      <option value="Sample - {{ product.title }}">{{ product.title }} </option>
      {% endfor %}
    </select>

    {# custom color #}

Enter Your Custom Color Options

    <input type="text" name="options[customColor3a]" placeholder="Custom Color 1" value="">

And this is what I use on the admin emails:

{% for item in order.lineItems %}
{% if item.purchasable.product.type.hasVariants %}
...
{{ item.description }}
{% if item.options.pattern | length %}
    {{ item.options.pattern }} |
{% endif %}

{% if item.options.customColor3a is defined %} |
    Custom Color 1: {{ item.options.customColor3a }}
{% endif %}
{% if item.options.customColor3b is defined %} |
    Custom Color 2: {{ item.options.customColor3b }}
{% endif %}
...

And finally, on the emails it looks like this:

Sample 1 - Product Name,
Custom Color 1: Green | Custom Color 2:

So I basically just want to hide the labels if nothing was selected. In the case above just not output "Custom Color 2". Any help would be appreciated!

Your customColor3a and customColor3b variables will always be defined so you need to check if empty.

{% if item.options.customColor3a is defined and item.options.customColor3a is not empty %} |
    Custom Color 1: {{ item.options.customColor3a }}
{% endif %}
{% if item.options.customColor3b is defined and item.options.customColor3b is not empty%} |
    Custom Color 2: {{ item.options.customColor3b }}
{% endif %}


P/T ContactForm Retrieving Custom fields Value after submitting form I'm trying to retrieve custom fields value after submitting a form. Trying to access the custom fields through the message element after the form is submitted always throws an error  that the custom fields variable does not exist.

Example that works:

Name:*
<input id="fromName" type="text" name="fromName" value="{% if message is defined %}{{ message.fromName }}{% endif %}">`

Example that doesn't work (custom fields):

Company:
<input id="fromCompany" type="text" name="message[fromCompany]" value="{% if message is defined %}{{ message.fromCompany }}{% endif %}">

Is it possible to retrieve custom field values after submitting the form?

In Craft 2.5 with Contact Form 1.4 I'm receiving the same error when using:

{% if message is defined %}{{ message.contactTel }}{% endif %}

I've gotten around this by using the Craft Request method getPost which can return a post value from an array. In the case of the original question, the following should work:

<label for="fromCompany">Company:</label>
<input id="fromCompany" type="text" name="message[fromCompany]" value="{% if message is defined %}{{ craft.request.getPost('message.fromCompany') }}{% endif %}">


Dukt Twitter plugin float issue I'm using the dukt.net Twitter plugin, in a Matrix field. It works fine locally, but on our dev server, something odd is happening, when I enter a Tweet url, like:

https://twitter.com/POLITICOEurope/status/596249628892364800

It fetches the tweet from the API correctly, but then displays it in the CP and in the templates as:

https://twitter.com/POLITICOEurope/status/5.96249628892E+17

So it converts it to a float. However, in the "fields_tweets_tweet" field in the database, it lists the correct long ID: 596249628892364800

And the odd thing is that it's happening on the dev server, but not locally. Anyone an idea where to start?

Pretty sure PHP is interpreting that string as an int. Doing a var_dump on the variable shows int(596249628892364800). That's pretty much PHP's type casting at work.

While you could cast the variable as a string, there's actually an unused variable called id_str which is ideal to use.

Edit the file twitter\fieldtypes\Twitter_TweetFieldType.php. Replace line 48 from:

$url = 'https://twitter.com/'.$tweet['user']['screen_name'].'/status/'.$tweet['id'];

To:

$url = 'https://twitter.com/'.$tweet['user']['screen_name'].'/status/'.$tweet['id_str'];


Similar entries with the greatest coincidence tags I have code

    {% set tags = entry.q_tags %}
    {% set entries = craft.entries.relatedTo(tags).order('score').find() %}
    {% for item in entries %}
      {% if item.id != entry.id %}
         .......
      {% endif %}
    {% endfor %}

But how to do that similar entries displayed order with the greatest coincidence tags?
Thank you. Sorry for my english

Please correct me if I am making an incorrect assumption. From your example, it looks like you're passing multiple tags to the search query, and by greatest coincidence you mean that you want the Entries that have the most matching tags that are part of your search, to appear higher in the results than Entries that may just have a single matching tag.

I don't believe this is possible without an additional plugin that helps with modifying the scoring and order of the search results.


EmailService now has Twig render email messages in safe mode EmailService now has Twig render email messages in safe mode.

  -- https://craftcms.com/changelog#build2903

I don't think this is really a bug as it's intended behaviour, but this is causing me a pretty big issue because my email layout has code in it like:

{% set contactDetails = craft.globals.getSetByHandle('contactDetails') -%}

But I think safe mode now means that the craft variable isn't actually available. I can pass it in manually when I'm sending non-standard emails with craft()->emails->sendEmail(), but has anyone found a way around this for the built-in ones like the activation/verification emails?

OK so it's pretty easy to pass additional variables to the email template using the email.onBeforeSendEmail event:

craft()->on('email.onBeforeSendEmail', function(Event $event)
{
    $event->params['variables']['craft'] = new CraftVariable();
});

Although I guess there are security reasons for email templates being rendered in safe mode in the first place so I don't know how much of a good idea this is...


How to get previous and next entry using the native GraphQL API? How do I turn these Craft queries into a GraphQL one?

// entry.twig

entry.getPrev({ section: "contentHub" })
entry.getNext({ section: "contentHub" })

I want to get the previous and next entry using the current entry

So I'm wondering the same thing, I'm using CraftQL as I need to support mutations, and I am close with this - but I get an error if I try to use $id instead of a hard-wired Int (e.g. 99):

query getEntryData($id: [Int]) {
  prevEntry: entry(prevSiblingOf: 99) {
    id
    title
    slug
    uri
  }
  nextEntry: entry(nextSiblingOf: 99) {
    id
    title
    slug
    uri
  }
  entryData: entry(section: investigations, id: $id) {
    id
    title
    slug
    uri
  }
}

I get the following error:

"message": "Variable \"$id\" of type \"[Int]\" used in position expecting type \"Int\".",

BUT then if I pass the $id as Int (and not [Int]) it works. Can't explain the typing difference.

query getEntryData($id: [Int], $sameId: Int) {

   prev:entry(prevSiblingOf: $sameId) {
    id
    title
    slug
    uri
  }
  next: entry(nextSiblingOf: $sameId) {
    id
    title
    slug
    uri
  }
  investigation: entry(section: investigations, id: $id) {
    id
    title
    slug
    uri
  }
}


How to build a sentence based on tags I try to build a complete sentence based on tags as follows:

This is a sentence with tag1, tag2 and tag3.

My code is:

{% set topics = entry.topics.first %}

{% for topic in entry.topics.offset(1) %}
    {% if topic != entry.topics.last %}
       {% set topics = topics ~ ', ' ~ topic %}
    {% endif %}
{% endfor %}

This is a sentence with {{ topics }} and {{ entry.topics.last }}.

My problem is that the if clause does not work. The results is always:

This is a sentence with tag1, tag2, tag3 and tag3.

I think it'll be easier and more efficient to achieve that if you use the loop functionality instead of querying the actual tags. I think this code does what you want:

{% set topics = '' %}

{% for topic in entry.topics %}
    {% set topics = topics ~ topic ~ (loop.index < loop.length-1 ? ', ' : loop.index < loop.length ? ' and ') %}
{% endfor %}

This is a sentence with {{ topics }}.