How do I add class to redactor format list?

Your example code attempts to create a new Redactor instance, which (as Brad says) won't work inside the control panel (where Craft has created the Redactor instances already).

You can, however, use the Redactor config files to add an element with the classname .note. To do that, add the following to the file config/redactor/Standard.json (or if you configured your RichText field to use a different configuration, the JSON file corresponding to that configuration):

"formattingAdd": {
  "note": {
    "title": "Note",
    "args": ["p", "class", "note"]
  }
}

Note that the first parameter in the args property is the tag which the .note element will use – according to the Redactor docs, only p, pre, blockquote, div and heading tags can be used with formattingAdd.

Also note that unless you add some custom CSS, the .note will – of course – not be styled any differently than a normal paragraph.

Unfortunately, there's no way to add custom CSS and JavaScript to the Control Panel without a custom plugin – either by writing your own or by installing the CP CSS and CP JS plugins.


I think that you actually want to use 'and' rather than 'or'. 'Or' would return all entries. This is also assuming that you have predefined the 'startDate' and 'endDate' variables.

{% set params = {
    section: 'exhibitions',
    startDate: 'and, >= ' ~ startDate ~ ', <= ' ~ endDate,
    order:'startDate desc'
} %}

{% set startedThisYear = craft.entries(params) %}

If you haven't already done so, you may need to format 'startDate' and 'endDate' variables first.

startDate: 'and, >= ' ~ startDate|date('Y-m-d') ~ ', <= ' ~ endDate|date('Y-m-d')

See this answer for another example.


Craft 3 plugins - Logging in a separate *.log file

Edit 2

I came up with a far far far better approach after a little brainstorming. I'll keep my old answer here but you should probably just use the first snipped.

In your main Pluginfile.php

public static function log($message){
    Craft::getLogger()->log($message, \yii\log\Logger::LEVEL_INFO, 'your-plugin-handle');
}

public function init(){
    $fileTarget = new \craft\log\FileTarget([
        'logFile' => __DIR__ . '/pluginName.log', // <--- path of the log file
        'categories' => ['your-plugin-handle'] // <--- categories in the file
    ]);
    // include the new target file target to the dispatcher
    Craft::getLogger()->dispatcher->targets[] = $fileTarget;
    ....
}

Explanation: categories is an array of all categories that should be in the log file. You usually want to allow only categories of your own plugin (you have to use an unique identifier in case certain other developers try to add the same category). Whenever you want to log something with the Craft/Yii log method that match one of your given categories in the array it will be logged in your file as well.

Old answer

Create this file somewhere in your plugin

FileTarget

class FileTarget extends \yii\log\FileTarget{

    // an array of categories that should be logged
    // note: your target receives all `Yii::log()` messages
    // but you can filter them with this array
    // if you want to track all messages of type 'application' as well
    // just include it in the array
    public $categories = ['a-category-that-you-would-like-to-log']; //<- usually your plugin handle or something

    // set the file path
    public function setLogFile($path = __DIR__){
        // I'm lazy so I just use the current location since it's in my 'src/' folder anyway
        // you can use Crafts default folders or whatever you like
        $this->logFile = $path . '/test.log';
        return $this;
    }

    // Optional -> a callback that formats your messages
    // remove this function if there is
    // no formatting needed or if you want to use the default
    public function formatMessage($message)
    {
        list($text, $level, $category, $timestamp) = $message;
        $level = 'Your fancy plugin Name';

        if ($category == 'a-category-that-you-would-like-to-log') {
            return date('Y-m-d H:i:s', $timestamp) . " [$level][$category] $text";
        }
    }
}

In your Plugin main file

public static $_fileTarget;

public static function log($message){
    if(self::$_fileTarget === null){
        /** @var FileTarget _fileTarget */
        self::$_fileTarget = Craft::createObject('namespace\pluginhandle\filetarget');
        // set the path
        self::$_fileTarget->setLogFile();
        // include your target to the current dispatcher targets
        // -> all messages are tracked in your target as well.
        Craft::getLogger()->dispatcher->targets[] = self::$_fileTarget;
    }

    // just use the default Craft/Yii logging method but with your category
    Craft::getLogger()->log($message, \yii\log\Logger::LEVEL_INFO, 'a-category-that-you-would-like-to-log');
}

Usage

Plugin::log('Lorem ipsum');
Craft::getLogger()->log('Lorem ipsum', \yii\log\Logger::LEVEL_INFO, 'a-category-that-you-would-like-to-log');
Craft::info('Lorem ipsum', 'a-category-that-you-would-like-to-log');

Maybe we could create a feature/pull request in order to create this feature by default. So every Plugin receives it's own category (by plugin handle) and if these categories are recognized the logger logs them in a separate file

Edit (thanks Andrew for mentioning it):

Note with this method I just add an additional target to the dispatcher that creates log files. So you'll insert 2 messages: one in the default storage/logs folder together with all the other requests and one in you custom log folder thus you are still able to use the great Yii2 Debug Toolbar and you can ask clients to hand over their plugin related logs to see what's going on


Render Field from FieldHandler in FreeForm Craft CMS

To pull an individual field from a form, use the form.get("myFieldHandle") method.

Simple example using the field.render() method:

{% set form = craft.freeform.form("myFormHandle") %}

{{ form.get("firstName").render() }}

Or a more custom example:

{% set form = craft.freeform.form("myFormHandle") %}
{% set firstName = form.get("firstName") %}

<label>{{ firstName.label }}</label>
<input name="{{ firstName.handle }}" value="{{ firstName.value }}" />
{{ firstName.renderErrors() }}

Examples from Freeform documentation

Note from the Freeform's docs:

  When using with HTML blocks or Submit buttons, use the hash value provided in property editor in Composer as the handle. Example code would look like:
  {{ form.get('Ajx7jNxXL').render }}


Cast Entry to appropriate type to access fields and functions in module

The actual answer is mostly unrelated to your question, but I wanted to provide some context, first!

Entry Types don't get their own PHP classes. All Entries are just instances of the craft\elements\Entry class, distinguished by their section ($entry->getSection()) and type ($entry->getType()) values.

If you need to check the section and type of your entry, you can compare against the sectionId and typeId properties. Keep in mind that these IDs may be different, across environments, so it's better to use the handle and keep it in sync with your project.yml:

if ($entry->getSection()->handle == 'mySectionHandle' && $entry->getType()->handle == 'myEntryTypeHandle') {
  // Your logic!
}

Ok, now on to the error you're seeing!

Calling unknown method: craft\elements\db\AssetQuery::getUrl()

This is actually telling you that the accessed field/property (photo) returns an object that doesn't have a getUrl() method.

Unless relational field data is eager-loaded, accessing its property will return an ElementQuery (in your case, an AssetQuery), prepped to return the related Elements.

So, before accessing methods on the expected value (an Asset Element), you have to execute the query:

$photo = $entry->photo->one();

if ($photo) {
  // At least one photo was attached! You can safely access the Asset object's properties + methods:
  $url = $photo->getUrl();
} else {
  // Set a default:
  $url = 'https://...';
}


Sprout Forms - Possible to reduce available field types in form builder

Sprout Forms for Craft 3 only displays fields that can be used on the form.

Craft 2 answer:

In Sprout Forms for Craft 2, it is not possible to toggle the visibility of the fields available, it displays all fields that can be received by the form.

Sprout Forms does break out the fields listed into option groups, so with a training-based approach, you could show a client that only the Standard Fields are supported and that all the Custom Fields require a developer to get implemented properly.

Another approach could be to use a plugin like Control Panel CSS and hide the Custom Fields option group:

.sprout-field-modal .fieldtoggle [label="Custom Fields"] {
  display: none;
}


Check if a Relationship field has a relationship without extra query

There isn’t currently, but it’s on our list to make it possible.

UPDATE

As of Craft 2.5, you can set relational field params to 'not :empty:' or ':notempty:' to only show elements where something is selected within the field; and you can set them to ':empty:' to only show elements where nothing is selected within the field.


Change matrixblock field value before save element

After a bit of testing, it appears you don't have anything to do to have your values saved, just set them and Craft will take care of the rest.
    Event::on(
        Elements::class,
        Elements::EVENT_BEFORE_SAVE_ELEMENT,
        static function (ElementEvent $event) {
            $element = $event->element;
            if ($element instanceof Entry && $element->getSection()->handle === 'testSection') {
                /** @var MatrixBlock[] $blocks */
                $blocks = $element->getFieldValue('testMatrix')->all();
                foreach ($blocks as $block) {
                    $block->setFieldValue('automaticField', uniqid('some unique value', false));
                }
            }
        }


Using pagination on a page with url with query string data

In most Craft projects I do I'll create a pagination include file so anything I need that requires pagination, I can just include that and I get the same pagination pattern anywhere within my site when I need it.

While you do have to set the country attribute with each link, sometimes it might get a little tedious to do this manually or you may expand your attributes to include other options, like ?country=123&distance=50.

This is where Craft's craft.request.getQueryStringWithoutPath() comes into play. In Craft 3 this has been changed to craft.app.request.queryStringWithoutPath. But you could do something like this:

{% if craft.request.getQueryStringWithoutPath() %}
  {% set queryString = "?" ~ craft.request.getQueryStringWithoutPath() %}
{% endif %}

Previous

Then no matter what URL attributes you have, they'll always be included within your pagination links.


Twig’s date filter is aware of the current Craft locale, so you should be able to create a DateTime after composing a string that the filter accepts (see PHP strtotime function docs, which the filter uses behind the scenes).

{% set day = 1 %}
{% set month = 'juni' %}
{% set year = 2016 %}

{% set dateString = [day, month, year]|join(' ') %}
{% set date = dateString|date %}

{{ date }}


How do I add a subcategory to the URL slug for a channel entry?

If you go into your Category Group’s settings and set the following settings:

Craft 2

Top Level URL Format: {slug}
Nested URL Format: {parent.uri}/{slug}

Craft 3

Category URI Format: {parent.uri}/{slug}

then you would be able to set your section’s Entry URL Format to this:

Craft 2

{myCategoryField.last.uri}/{slug}

Craft 3

{myCategoryField.inReverse().one().uri}/{slug}


I’ve built a plugin to allow control over what user groups can allocate permissions.

https://github.com/joshuabaker/Sanction


Something like this should do the trick:

{% set usersGroupedByCountry = craft.users.limit(null)|group('postaddress.country') %}

    {% for country, users in usersGroupedByCountry %}
        {% if country and users|length %}

{{ country }} ({{ users|length }})

        {% endif %}
    {% endfor %}

Note that if you want to order the list of countries, you'll need the SuperSort plugin. Here's how you would sort the list alphabetically:

{% set usersGroupedByCountry = craft.users.limit(null)|group('postaddress.country)|supersort('ksort') %}

Also note that if you have a lot of users (say, hundreds), it is probably a good idea to wrap the whole thing (including the {% set usersGroupedByCountry ... %} part) in a {% cache %} tag pair, for performance reasons.


I would run two queries and then you could utilise the completed() parameter:
https://craftcommerce.com/docs/craft-commerce-orders#completed

{% set pastOrders = craft.commerce.orders.completed(true).relatedTo({targetElement: currentUser, field: 'deliveryGuy'}).find() %}
{% for order in pastOrders %}
   {{order.id}}
   {{order.orderStatus.name}}
{% endfor %}

{% set pendingOrders = craft.commerce.orders.completed(false).relatedTo({targetElement: currentUser, field: 'deliveryGuy'}).find() %}
{% for order in pendingOrders %}
   {{order.id}}
   {{order.orderStatus.name}}
{% endfor %}


You can do this with the default Email Dropdown field (no JS needed!). The Email Dropdown field lets you create a mapping between an item in the dropdown and an email:

Website Issues: websupport@mywebsite.com
Information: info@mywebsite.com

The Email Dropdown field obscures those emails in your template. And when you set up your Notification Email, you can reference your Email Dropdown field by its handle in your Recipients setting: {emailDropdownFieldHandle}

In the case you ever did wish to add JS to your templates, the best way to add it to your template is to use Template Overrides.


Looping through returns nothing after using dynamic routes to get the entry type and category

{% if not entries %} never executes, even if i enter complete nonsense in the url.

You’re not ensuring that segmentCategory is a valid category slug anywhere. If it’s not, then category will get set to null, which will basically prevent it from affecting the following relatedTo param.

So right after grabbing the category you should make sure it exists;

{% set category = craft.categories.slug(segmentCategory).first() %}
{% if not category %}
  {% exit 404 %}
{% endif %}

  the array entries is never outputs anything

I think this is because your relatedTo parameter isn’t set up correctly. If the used/new categories are being assigned to the entries via a Categories field on the entry, then the category should be set to the targetElement property, not sourceElement, since the category is the target element of the relation. And you can just get rid of the current targetElement stuff, which should have been sourceElement, but is redundant and doesn’t need to be specified anyway.

{% set entries = craft.entries({
    type: segmentEntryType,
    relatedTo: { targetElement: category }
}) %}

  Ok, now i get the posts, but if i pass an invalid string to the segmentEntryType the template still loads.

This conditional:

{% if not entries %}

should be:

{% if not entries|length %}

(At this point in your template, entries will be a defined ElementCriteriaModel regardless of whether it matches any entries. Including the length filter in your conditional will force it to execute the DB query and return the actual results.)


I am unable to correctly return the url of an uploaded asset

I found the answer in a similar post here: Image asset url is not being output

My problem was with my Asset Source settings. Now that I think about it, it's obvious: I had no public URL declared for assets from my 'Uploads' source. Giving that a public url fixed the problem.

As I said, it's obvious now, but it'd be nice in the documentation could make even just a small reference to this.


Check if current entry is in loop and add class

Firstly, from the Craft docs on routing:

  If the URI matches an entry’s or category’s URI, the
  section’s/category group’s template will get loaded, and the matched
  element will be made available to the template via a pre-populated
  entry or category variable.

This means if the page you are viewing relates to an entry, Craft will have already created a variable called entry, which will contain the EntryModel for that entry, so it’s best to avoid re-assigning the entry variable in a template used for an entry to avoid confusion.

To address your question, you need to check if the current URL matches the URL of an entry in the loop, which you can do by checking against [craft.request.url][2] like this:

{% for catEntry in craft.entries.section('category_name').limit(4) %}
    {% if craft.request.url == catEntry.url %}

{{ catEntry.title }}

    {% else %}

{{ catEntry.title }}

    {% endif %}
{% endfor %}


How could I submit the Charge plugin using Ajax?

You need to specify the HTTP method used by the $.ajax method.

By default, it uses GET, but you need to submit the form using POST.


Get entries filtered by date fields, one of which might be empty (and paginate them)

There's no way to simply add it to that query you have. But you can use the following workaround.

You first do all the logic within such conditionals you actually wanted to avoid, but instead of getting the ElementModels directly, you do an extra step and get / collect the entries' IDs using the ids() method.

When you're ready, use these IDs with the id property in a second ElementCriteriaModel. This you can paginate like you want!

Edit:Here's some example code!

{% set cutoffDate = 'now'|date_modify('- ' ~ '7' ~ ' days') %}
{% set events = craft.entries.section('events').order('dateStart desc') %}

{% set eventIds = [] %}
{% for event in events if (event.dateEnd ? event.dateEnd : event.dateStart) >= cutoffDate %}
    {% set eventIds = eventIds|merge([event.id]) %}
{% endfor %}

{% set filteredEvents = craft.entries.id(eventIds).fixedOrder('true') %}


Is there any alternative for the Redactor plugin in Craft 3?

Rakhi, based on your comment on the question, you're missing the video and imagemanager in the plugins array.

Example:

"plugins": [
    "alignment",
    "fontcolor",
    "video",
    "imagemanager",
    "table",
    "fullscreen"
],

Read more about it Here and Here


Query section entries based on start/end date and type

Update

Found the solution for my first question.

For current events my working solution is:

{% set entries = craft.entries()
  .section('messages')
  .type('event')
  .startDate('<= ' ~ now|date('c'))
  .endDate('>= ' ~ now|date('c'))
  .orderBy('startDate asc')
  .all()
%}

{% for entry in entries %}

{{ entry.title }}

{% endfor %}

For upcoming events a simpler solution is:

{% set entries = craft.entries()
  .section('messages')
  .type('event')
  .startDate('> ' ~ now|date('c'))
  .orderBy('startDate asc')
  .all()
%}

{% for entry in entries %}

{{ entry.title }}

{% endfor %}

I can't figure out how to get my second question working.

I need to query all messages (type: news and events) and exclude current and upcoming events. The output: all messages of type news and all messages of type events that happened in the past. Including pagination.

It should be a combination of this i think:

{% set news = craft.entries()
  .section('messages')
  .type('news')
  .all()
%}

{% set events = craft.entries()
  .section('messages')
  .type('event')
  .startDate('< ' ~ now|date('c'))
  .endDate('< ' ~ now|date('c'))
  .all()
%}

Together combined with ordering by post date and pagination. Help! :-)


The problem with putting them in your templates folder is now PHP/Craft is going to try and serve them.  Meaning that you've got the overhead of PHP and Craft when trying to request every single asset instead of if they were in the public folder where Apache can instantly serve them (orders of magnitude faster).


Check if the matrixField is populated:

{% if entry.matrixField|length %}{% endif %}
There are two options to pull out fields from a block type.

Option A: use a for-loop pointed at your Matrix field

// If you want to output block of a certain type
{% if entry.matrixField|length %}
    {% for block in entry.matrixField.type('yourBlock') %}
        {{ block.field1 }}
        {{ block.field2 }}
        {{ block.fieldN }}
    {% endfor %}
{% endif %}

// OR multiple types
{% if entry.matrixField|length %}
    {% for block in entry.matrixField %}
        {% if block.type == "yourBlock" %}
            {{ block.field1 }}
            {{ block.field2 }}
            {{ block.fieldN }}
        {% elseif block.type == "yourBlock1" %}
            {{ block.field1 }}
            {{ block.field2 }}
            {{ block.fieldN }}
        {% endif %}
    {% endfor %}
{% endif %}

Option B: use simplified method of a for-loop

{% if entry.matrixField|length %}
    {% set yourBlock = entry.matrixField.type('yourBlock') %}
    {% for block in entry.matrixField %}
        {% switch block.type %}
            {% case "yourBlock" %}
                {{ block.field1 }}
                {{ block.field2 }}
                {{ block.fieldN }}
        {% endswitch %}
    {% endfor %}
{% endif %}

Also check Craft's documentation about Matrix Fields.


Commerce Custom Shipping Methods via Plugin

Ok, so what you're doing is returning a new instance of a shipping method class - this class must meet the Shipping Method interface - documented here: https://craftcommerce.com/docs/shipping-methods#shipping-method-interface

That is, you must implement each of those functions as defined by the interface in your shipping method class.

You'd define this class in a file of it's own named after the class, and in your base plugin file you require this class definition to bring it in to scope.

The same goes for your shipping rules - you again create a class that meets the interface and then require that in your main plugin file (or wherever you need to access the rule).


dynamic urls for channel/structure that's linked to the main structure

I'm not sure to understand what you're trying to solve but... have you tried using the getElementRoute hook to bypass the default Craft routing and apply any custom processing/routing you need?


Error reporting Freeform submission jumps to top of page

By setting the action: "#errortag" seems to stop the form submitting if there are no errors.

So instead I have added the following code and this seems to work;

{% if form.hasErrors %}
{% includejs %}
$(document).ready(function () {
    $('html, body').animate({
        scrollTop: $('#formErrors').offset().top-110
    }, 1000);
});
{% endincludejs %}
{% endif %}


Is it possible to reorder globals in the back end?

It's currently not possible to change the order in the control panel, but we might look into that for a future release.  They are currently set to display alphabetically.


Locale URL segment being duplicated, eg https://website.test/en/en/

Your issue is that the @web alias resolves to this:

  The URL to the folder that contains the index.php file that was loaded for the request

Now that you’re serving your English site from web/en/index.php, @web will already resolve to http://website.test/en.

The alias @web/en you are using for your site’s base URL does therefore resolve to http://website.test/en/en

So you can fix it be using @web for your base URLs, or what I would rather recommend is to serve all your sites from a single web/index.php file (which is possible now in Craft 3). With this change @web will always refer to http://website.test and you need to use @web/en again in your site settings.


No, there can only be one author. But what you can do is to add one or more custom user fields to your entry type and use these to assign different type of users to your entry (all contributing authors, photographers, etc.).

Set user privileges like Douglas describes in his answer, to allow multiple authors to edit entries in your section.


Verbb Wishlist plugin see if item is in specific list

You can pass a list type handle in the query like this:
{% set compare = craft.wishlist.item(entry.id, null, 'compare') %}

I had to look at the source code for the craft.wishlist variable to confirm what that's doing, though! The Wishlist docs on checking if an item is in a list aren't super-clear on this, but passing the list type handle in the query will fetch the first list that matches that handle for the current user. If you have multiple lists for that list type, only the first one that the query returns will be checked for the item.


It makes sense, when it's a task that should only be done once and is directly related to the asset.

A good example I have of an Asset custom field is a field allowing the content-administrator to define where an images focal point is positioned e.g. top left, bottom right, top right, etc.

I'm able to make use of the field EVERY time I display the image asset, but only need to deal with the custom field, once.

Part deux (in answer to your comment):

Yes, in my experience, although you can also double click an asset from the new/edit entry screen and see it's custom fields e.g. "Focal point position". See image below...


How can I output the Field Name in my template?

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

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

.

Note: There is no documentation on the FieldModel yet, but if you want to know more, take a look at craft/app/models/FieldModel.php.

This is a list of all attributes supported by the Model:

groupId
name
handle
context
instructions
required
translatable


Programatically creating a user not appearing in Users index table

For anyone's future benefit - this happens due to the fact I'm adding the user in the sproutForms.saveEntry hook. That happens after it messes around with the fieldContext and contentTable options for the Entry. As such, the user is getting saved to the wrong context, so it won't appear...

A quick workaround for this is to move the following lines in SproutForms_EntriesService.php:133-135 to lines 120. This resets the field context back before the hook is called.

if ($transaction !== null)
{
    $transaction->commit();

    SproutFormsPlugin::log('Transaction committed');
}

// Reset our field context and content table to what they were previously
craft()->content->fieldContext = $oldFieldContext;
craft()->content->contentTable = $oldContentTable;

Craft::import('plugins.sproutforms.events.SproutForms_OnSaveEntryEvent');

$event = new SproutForms_OnSaveEntryEvent(
    $this, array(
        'entry'      => $entry,
        'isNewEntry' => $isNewEntry,
        'event'      => 'saveEntry',
        'entity'     => $entry,
    )
);

craft()->sproutForms->onSaveEntry($event);


get session data by cookies CraftSessionId

I don't think I'd use PHP's session for this at all, but recently posted some thoughts on a similar question here https://craftcms.stackexchange.com/a/14188/57 about using custom tokens or authorization headers to perform the authorization.


Use craft.entries:

{% for job in craft.entries.section('jobs') %}

    Title: {{ job.title }}

    Company: {{ job.company }}

    Email: {{ job.email }}

{% endfor %}


Craft Commerce - Advanced Product Options & Pricing

I can't see this being a problem. All variants can have their own pricing. You can also use relations to mix and match different things if you'd like.

There is a fine art printing section on the Image Science web site that may be an example of what you are thinking. There is a full write up of what it took to create the web site here: The Epic Journey to the New Image Science Website.


Craft Commerce 2: Subscription Payment Gateway

According to the Commerce 2 docs, the only first-party gateway that currently supports subscriptions is Stripe.

Again, according to the Commerce 2 docs, the Stripe plugin is available for free on the plugin store.


I don't know a plugin like this for Craft. But this solution does a similar thing. Maybee it works for you: Let clients set crop position for images.
Otherwise you could also take a look on the focuspoint plugin: https://github.com/smcyr/Craft-FocusPoint


How can I merge a Modified Date and Time in Twig?

Having done some further testing and research I believe this is a case of having to merge two date objects and ensuring that these are set as date/time objects when merging them into a variable.
Here are some examples way:

{% set thisWeeksDayAndTime = thisWeeksDay|date() ~ ' ' ~ classStartTime|time() %}

{% set thisWeeksDay = page.startDate|date_modify('this  ' ~ classDay ~ ' ' ~  classStartTime|time()) %}


Images much larger on server and page than the local version

This is likely to be a combination of factors.

Firstly; GD isn't all that great, so if you can get ImageMagik installed it's possible you'll get better results.

Secondly; This can depend on the image format too. PNGs for example are far more complicated to save optimised and it's unlikely that a PNG generated by a server is going to match the level of optimisations you can get locally through tools like TinyPNG and ImageOptim. PNGs have many more options for quality control than JPG's simple slider. Try to avoid transforms on anything other than JPGs.

Thirdly; check you're uploading an image that's larger than the crop you're creating. Craft has a horrible behaviour of blowing up images to match the crop. It's not really cropping, it's just taking any image and making it the size requested. That can mean 'cropped' images larger in filesize and dimension than the source.


How can you check if a field exists in a section, not by entry?

The solution is to getEntryTypes() from your section and then access the getFieldLayout() to get to the getFields() (thanks again @Khalwat!). Example:

{% for section in sections %}
    {% if section.getEntryTypes()[0].getFieldLayout().getFields()[0].getField().handle == 'specificfield' %}
        do something
    {% endif %}
{% endfor %}

Notice though that I specifically search for the first occurances, in (most) other cases you should foreach the getEntryTypes() and getFields()


Setting User field type from a front end form

Maybe I don't quite get your problem, but I actually don't see any difference between posting child entries (the patients) related to a parent user and posting questionair entries related to a child entry.

You need a hidden field like this for the child registristration.

{% parentId = entry.authorId %}
...
<input type="hidden" name="fields[parentUsersField][]" value="{{ parentId }}">

You can now link to the child entry and allow the parent to enter the questionair form.

{% set childId = entry.id %}
...
<input type="hidden" name="fields[childEntriesField][]" value="{{ childId }}">

Keep in mind that relation fields can hold multiple elements, even if set a limit in the field settings; so you need to post an array using the syntax show above. There's other more  complete code examples here on Stack Exchange for having relational fields in a from (i.e. "Creating comments via a related section").

And yes, using a channel for the questionairs is a very flexible and clean way to structure the relation in my opinion.


How to transform German umlauts when creating slugs?

Try enabling the config setting limitAutoSlugsToAscii, that should do what you want.


Template error: A template that extends another one cannot have a body

In your base.html you need to include a block section, so something like this:

<!DOCTYPE html>

<meta charset="UTF-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

{% block content %}{% endblock %}

Then in your contact.html you need to wrap your main markup in the same block, like this:

{% extends "_layouts/base" %}
{% macro errorList(errors) %}
{% if errors %}

{% for error in errors %}

{{ error }}

        {% endfor %}

{% endif %}
{% endmacro %}
{% from _self import errorList %}

{% block content %}
<form method="post" action="" accept-charset="UTF-8">
{{ getCsrfInput() }}
<input type="hidden" name="action" value="contactForm/sendMessage">
<input type="hidden" name="redirect" value="../public/index.php/contact.html">

Your Name

<input id="fromName" type="text" name="fromName" value="{% if message is defined %}{{ message.fromName }}{% endif %}">
{{ message is defined and message ? errorList(message.getErrors('fromName')) }}

Your Email

<input id="fromEmail" type="email" name="fromEmail" value="{% if message is defined %}{{ message.fromEmail }}{% endif %}">
{{ message is defined and message ? errorList(message.getErrors('fromEmail')) }}

Message

<textarea rows="10" cols="40" id="message" name="message">{% if message is defined %}{{ message.message }}{% endif %}</textarea>
{{ message is defined and message ? errorList(message.getErrors('message')) }}

<input type="submit" class = "btn btn-submit" value="Send">
</form>
{% endblock %}

So you are basically saying create an area called content in your base.html and you want to fill this area with the markup wrapped in the content block inside your contact.html. You can call the block whatever you want, so here we've called it content, it doesn't have to be that, but it seems a fairly logical name for it.

You can have more than one block in your base.html, if you want. For instance you could have a header, content and footer blocks. All you need to remember is to use the same names inside the template file you are extending the base.html from.

More information can be found in the Twig documentation


It’s currently only possible via direct manipulation of the entries in your database.

You will first need to visit your sections table to determine the desired section ID, and then the entrytypes table to determine the desired entry type ID.

Once you have those, find your entry’s row in the entries table, and change its sectionId and typeId columns accordingly.

NOTE: If either of the the old/new sections are Structures, there’s quite a bit more work involved, and your best bet will be to write some PHP code to handle the migration. See https://craftcms.stackexchange.com/a/4467/9 for a complete example of how to do that.


Click on USD under Commerce->Settings->Payment Currencies and change the dropdown from USD to EUR.  That will become Commerce's new base/primary currency.

If you also want to support USD, you can add it as a second currency now and setup a conversion rate.


When setting up the category, you should be able to specify the URI Format which in your case would be "our-work/{slug}" then setting the template field to point where ever your category template is (You could point this at the same template as the overview and do a some checks but if you're beginner you'd probably better off having them in separate files).

Once you're loading in the new template, you need to get the projects that are related to the category by doing:

{% set projects = craft.entries.section('projects').relatedTo(category).all() %}


Easily update the query string with a link

OK, this should be a working code example:

{% set queryParams = craft.app.request.queryParams %}
{% for key, value in queryParams %}
  {% set url = siteUrl ~ craft.app.request.fullPath %}
  {% set arr = queryParams | filter((v, k) => k != key) %}
  {% if arr|length > 0 %}
    {% set url = url ~ '?' ~ arr|url_encode %}
  {% endif %}
  {{key}} {{value}} x
{% endfor %}

Line by line:

Create an array based on the current request parameters:

{% set queryParams = craft.app.request.queryParams %}

Loop through the array and get the key/value pair:

{% for key, value in queryParams %}

While inside the loop, get the URL that we want to modify, minus the request params:

{% set url = siteUrl ~ craft.app.request.fullPath %}

Filter a local copy of the array to remove the current key:

{% set arr = queryParams | filter((v, k) => k != key) %}

If there are any parameters left, modify the URL we previously set with the remaining parameters:

{% if arr|length > 0 %}
  {% set url = url ~ '?' ~ arr|url_encode %}
{% endif %}

Output the link that will load the page without the current parameter.

{{key}} {{value}} x

I would probably do this in a macro to keep the template code a bit cleaner and easy to read.


Since Global Sets are elements just like entries, users, etc., you can create API endpoints that are all about them:

'globals/<handle:\w+>' => function($handle) {
    return [
        'elementType' => 'GlobalSet',
        'criteria' => ['handle' => $handle],
        'first' => true,
        'transformer' => function(\Craft\GlobalSetModel $globalSet) {
            return [
                'foo' => $globalSet->foo,
                'bar' => $globalSet->bar,
            ];
        }
    ];
}

You can also manually query for Global Sets, to include their data in an endpoint that’s tied to another element type:

'my/other/endpoint' => [
    'elementType' => 'Entry',
    // ...
    'transformer' => function(\Craft\EntryModel $globalSet) {
        // ...

        // Fetch a global set
        $criteria = craft()->elements->getCriteria(ElementType::GlobalSet);
        $criteria->handle = 'myHandle';
        $myGlobalSet = $criteria->first();

        // Include the global set content in the response data
        return [
            // ...
            'foo' => $myGlobalSet->foo,
            'bar' => $myGlobalSet->bar,
        ]
    }
]

Craft also provides a couple methods for fetching Global Sets by ID or handle, so if that happens to be exactly what you need, feel free to use those:

craft()->globals->getSetById()
craft()->globals->getSetByHandle()


Is there a way to get categories relating to a specific entry within a plugin?

Since groundsQuestions is a category field, calling it will return an element query on which you can call one(), all(), etc.

For example:

$groundsQuestions = $entry->groundsQuestions->all();


Thanks. I think this is what happened. When i saved the entry change i did change the Enrty Template name. However, it seemed to have generated it back to articles/_entry.

Then i went in again and updated the name back to the real name i was using.


Glad to know that it is working on your server. On Windows, you may need to add the paths manually. Please follow our docs about how to add the paths on Windows.


Error: "Tried to read the folder contents...but could not"

Try changing the 664 through SSH instead of manually. These three folders need the right permissions:

craft/app/
craft/config/
craft/storage/

source: https://craftcms.com/docs/installing

Edit: Have you tried removing the content of the Cache?


Import Large Number of records - 300,000

Increasing your servers available memory and execution time can help increase the number of items you can import in a single file, but with the number of records you're dealing with it's likely, you'll need to break your import into multiple steps.

Consider breaking up the import files into smaller batches that can be imported within your environment's memory limit. As a first step, you could manually test for a limit of the max number of entries you can import.

This could be done by going back to the source that provided you the large CSV file and asking if they can provide you several CSV files of 50,000 records each, 10,0000 records each, or whatever number of records you found to be your limit. You may end up with lots of files and that's fine.

You could potentially also write a script that takes your CSV file or converted XML file and breaks it into several files on your own.

I'm not familiar with all the options in the Import and FeedMe plugins. My firm develops Sprout Import and we support batch importing multiple files. Sprout Import also requires data to be in a specific JSON format, which would likely require writing an additional script in your case as well.


Is there a way to filter calendar results by location?

Yes, you can achieve this by using the search parameter on calendar.events just like you would with regular Craft Searching.
search: "customField:myvalue*"

It might also look something like this in your template:
{% set eventOptions = {
  rangeStart: 'now',
  rangeEnd: '3 months',
} %}

{% set events = craft.calendar.events(eventOptions).search("location:test") %}

{% for event in events %}
   ...
{% endfor %}


LastPass causing incorrect email address to be saved in new user form

After disabling my password manager, LastPass, my email address stopped sneaking into the username field. Upon closer inspection, here's what was happening:

After filling out the new user form and clicking 'Save,' you are prompted for your password. THIS is where LastPass misbehaves, or more accurately, does what it's designed to do but not very helpfully. It not only fills the password input, but replaces the contents of the 'Username' field with your email address (that is, the email address associated with the login stored in LastPass). It's easy to miss this, however, with the transluscent white overlay.

Solution

Configuring LastPass to not fill forms on the new user page isn't helpful, as you likely want it to enter your password when prompted. The best solution I could come up with is to clone my Craft login, delete the email address / username, and add 'New User' to the label. Now when prompted for the password I can select that login and avoid overwriting the new user's email address.


Is it possible to output month names in my native language?

Yes, the date() filter you use (see Twig docs) allows you to format dates with the same formating characters as the php date function takes. All language dependent parts are returned in the language of the current locale. I don't know if you can change that primary locale in the control panel, but you could do that in the DB.

As you noted in the comments to your question, you want the CP to be in english. This is possible even if you set the site's locale to another language; the site's locale and the user language for the CP are different things.


The autoloader won't load files in the folder assets as already stated it is all explained here. Your asset bundles should be in a folder called resources otherwise Yii won't register them in its classmap automatically.

Your namespaces must represent your folder structure. The namespace ns\prefix\controller must be for a file in vendor\ns\prefix\src\controller so your namespace ns\prefix\assets will search for a file in ...vendor\ns\prefix\src\assets but you have to include the resource on your own via require_once since Yii won't so it because you are in the wrong folder

The easiest solution would be to create a folder resources and use the namespace ns\prefix\src\resources

Or you can - like stated in the docs - use your plugin root path as well recoveryfinder\entriesbygroup


Somehow, the images were created thinking Imagick wasn't installed. Clearing the cache forced the images to be recreated and seems to have fixed it.


Why won't the Import plugin accept this JSON string?

You're close!

The method that Lindsey recommends should work with the following method of adding content to a field:

$entry->getContent()->setAttributes(array(
    'tableFieldHandle' => json_encode($tableData)
));

However, the modifyImportRow documentation uses the (arguably better) method:

// Set modified content
$element->setContentFromPost($content);

Using this method, you should add an array to a table field, rather than a JSON strong, since setContentFromPost() will call the relevant methods to format the field data appropriately for the database, so you don't need to worry about it.

So if you use:

$content[$handle] = $tabledata;

then add it to the element using:

// Set modified content
$element->setContentFromPost($content);

it should work.

The full code for the modifyImportRow function in your plugin should now look like this:

/**
 * Modify data just before importing
 *
 * @param BaseElementModel $element  The current element receiving import data.
 * @param array            $map      Mapping of data between CSV -> Craft fields.
 * @param array            $data     Raw data provided for this row.
 */
public function modifyImportRow($element, $map, $data)
{
    // Map data to fields
    $fields = array_combine($map, $data);

    // Initialize content array
    $content = array();

    // Arrange your content in a way that makes sense for your plugin
    foreach ($fields as $handle => $value) {

        if ($handle=="myTableHandle"){

            $rows = explode(',', $value);

            $tabledata = array();

            foreach ($rows as $row) {
                $rowarray = explode(':',$row);

                $rowdata['col1'] = $rowarray[0];
                $rowdata['col2'] = $rowarray[1];

                $tabledata[] = $rowdata;
            }

        }

        $content[$handle] = $tabledata;

    }

    // Set modified content
    $element->setContentFromPost($content);
}


Fetching entries by a Matrix block field value is actually quite complicated, and not possible to do in a single query – at least not using built in services like craft.entries.

Your idea of pulling all entries and looping through would work – but this kind of "brute force" solution might not scale that well, performance wise.

A better idea might be to first pull all the space Matrix blocks that have a true value for the isAvailable field, and then pull any entry belonging to the buildings section that has a relation at least one of those blocks.

Unfortunately, unlike the EntriesService (i.e. craft.entries), Craft doesn't expose the MatrixService to Twig, making the above hard to accomplish in a template.

For a clean & effective solution to this problem, I'd look to the excellent Low Blocks plugin.

With Low Blocks, you'll be able to pull all space blocks with a true value for isAvailable like this:

{% set spacesMatrixField = craft.fields.getFieldByHandle('spaces') %}
{% set spaceMatrixBlocks = craft.lowblocks.blocks.fieldId(spacesMatrixField.id).type('space').isAvailable('1') %}

After that, we can loop on the matrixBlocks variable in order to create an array containing the IDs of the entries "owning" these Matrix blocks:

{% set buildingEntryIds = [] %}
{% for block in spaceMatrixBlocks %}
    {% set buildingEntryIds = buildingEntryIds|merge([block.owner.id]) %}
{% endfor %}

And finally, we pull the entries using the buildingEntryIds array variable as the parameter to the id argument:

{% set entries = craft.entries.section('buildings').id(buildingEntryIds).limit(null) %}

Here's everything together, for cohesion:

{# Get Matrix blocks #}
{% set spacesMatrixField = craft.fields.getFieldByHandle('spaces') %}
{% set spaceMatrixBlocks = craft.lowblocks.blocks.fieldId(spacesMatrixField.id).type('space').isAvailable('1') %}

{# Get entry IDs #}
{% set buildingEntryIds = [] %}
{% for block in spaceMatrixBlocks %}
    {% set buildingEntryIds = buildingEntryIds|merge([block.owner.id]) %}
{% endfor %}

{# Get entries #}
{% set entries = craft.entries.section('buildings').id(buildingEntryIds).limit(null) %}

That should hopefully do the trick. If you're interested though, here's some more info on why your first attempt wouldn't work:

First, I'd like to point out that its important to realize that each chained "segment" (such as section or isAvailable) in a call to craft.entries in a template actually ends up as an attribute of an ElementCriteriaModel (an object Craft constructs to query the database). This means that

craft.entries.section('buildings').spaces.space.isAvailable('1').find

is actually the same as

craft.entries({
    section : 'buildings',
    spaces : null,
    space : null,
    isAvailable : '1'
})

It should be fairly obvious why this query won't do what you want; Craft has no idea that spaces.space.isAvailable is actually the "path" to a certain Matrix block type's field, and will consider each of those segments (spaces, space and isAvailable) as a separate attribute/argument.

Aside from the syntax issue, the real reason why you'll never be able to use something like spaces.space.isAvailable in a craft.entries query is that Matrix blocks aren't just regular, nested fields, but elements unto themselves (just like entries, categories or assets). Also, for any single entry there can be an indefinite number of instances of each block type. If you have multiple space blocks for a single entry, some with a false isAvailable value and some with true, how would Craft know if the entry should be returned or not?


Use a UUID for an entry ID in a URL path

You can use {uid} inside the "Entry URI Format" field.


Craft can't connect to the database (using ec2)

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.


Camera Orientation and image transforms?

The image processing library we use just recently added the support for us to be able to read image EXIF metadata from images, so it's on our list (among other things) to have transforms be aware of image orientation.


Do servers in a multi-server Craft setup need to share a storage directory?

Personally, I'd lean towards keeping the shared NFS volume.  It's not just the runtime folder, but things like backups, site logos, user avatars, etc. and anything else plugins might be storing in storage that you'd want to consider as well.


Display a new entry modal when clicking on a relation field

I'd rather look into nesting Super Table fields within your Matrix block types than relating Entries. The Entry element type and its relationship field come with a lot of inappropriate UI for the use case you're trying to solve.

Another approach would be to write a plugin that provides its own element type and relationship field / modal UI.


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

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

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

$criteria->limit = $batchSize;

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

Tested, and works.


Error with Craft Commerce & Stripe no longer supports API requests made with TLS 1.0

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


How can I update custom order fields in the frontend

Correct, you need to use fields[customFieldName] as the input name.

The following form should do it:

<form method="POST">
    <input type="hidden" name="action" value="commerce/cart/updateCart">
    <input type="text" name="fields[myCustomField]" value="Test123">
    ...
    <input type="submit" value="Update Custom Field">
</form>


Trying to create a new field returns "General Error: 1030 Got error 1 from storage engine"

I restarted my DB server and it fixed the issue. Sorry for the false alarm, but I've never seen something like that before. Should have tried the DB restart before.


Sprout SEO: Getting error on save, preventing updating "default" meta data

This issue came as a result of the MySQL DB sql_mode including the NO_AUTO_VALUE_ON_ZERO mode which affects how auto_increment columns work. When trying to create a new row entry it will only auto_increment if null is passed.

Full explanation here:

http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_auto_value_on_zero

This setting matched with the way the controller's actionSaveDefault function was setting the id to a blank value rather than a null value caused it to trigger this DB behavior of writing a 0 rather than auto_increment.

While the cause of the issue is not Craft or SproutSEO specific, this answer might help anyone else with the issue.

Check your MySQL DB sql_mode
If, NO_AUTO_VALUE_ON_ZERO is set make sure you're passing null if you want it to auto_increment


Can you hook into a Redactor field before render?

Probably several ways you could tackle this like with a custom Redactor JS plugin, but I'd probably write a Craft plugin that forked and extended the original Craft Redactor plugin.

From there, you could overwrite the Redactor field's normalizeValue() method and parse the input to make whatever changes you want before returning.


You will need to write a plugin with three responsibilities:

Keep track of which entries have been purchased
Set an entry to enabled when it has been purchased
Ensure that entries always have the correct status (enabled/disabled) whenever they are saved

For the first one, you will need to create a new DB table that can store records of which entries have been purchased.

In your plugin, create a records/ table with a MyPlugin_EntryPurchaseRecord.php file:

<?php
namespace Craft;

class MyPlugin_EntryPurchaseRecord extends BaseRecord
{
    public function getTableName()
    {
        return 'myplugin_entrypurchases';
    }

    public function defineRelations()
    {
        return array(
            'entry' => array(static::BELONGS_TO, 'EntryRecord'),
            'order' => array(static::BELONGS_TO, 'Commerce_OrderRecord'),
        );
    }
}

With that in place, the table will automatically get created when you install your plugin.

Next, give your primary plugin class an init() method where you can set up some event listeners:

<?php
namespace Craft;

class MyPluginPlugin extends BasePlugin
{
    // ...

    public function init()
    {
        craft()->on('commerce_orders.orderComplete', array($this, 'onOrderComplete'));
        craft()->on('entries.beforeSaveEntry', array($this, 'onBeforeSaveEntry'));
    }
}

Your onOrderComplete function will be responsible for recording the purchase in your entrypurchases table, and updating the entry’s status to enabled:

public function onOrderComplete(Event $event)
{
    /* @var Commerce_OrderModel $order */
    $order = $event->params['order'];

    // Look for a line item with an entryId option
    foreach ($order->lineItems as $lineItem)
    {
        if (!empty($lineItem->options['entryId']))
        {
            // Validate the entry ID
            $entryId = $lineItem->options['entryId'];
            $entry = craft()->entries->getEntryById($entryId);
            if (!$entry) continue;

            // Record the purchase
            $purchaseRecord = new MyPlugin_EntryPurchaseRecord();
            $purchaseRecord->entryId = $entryId;
            $purchaseRecord->orderId = $order->id;
            $purchaseRecord->save();

            // Enable the entry
            $entry->enabled = true;
            craft()->entries->saveEntry($entry);
        }
    }
}

And your onBeforeSaveEntry function will be responsible for making sure entries’ statuses are set correctly depending on whether they’ve been purchased:

public function onBeforeSaveEntry(Event $event)
{
    // Ignore for new entries
    if (!empty($event->params['isNewEntry']))
    {
        return;
    }

    /* @var EntryModel $entry */
    $entry = $event->params['entry'];

    // Ignore entries in other sections
    if ($entry->section->handle != 'mySection')
    {
        return;
    }

    // Has the entry been purchased?
    $purchaseCount = MyPlugin_EntryPurchaseRecord::model()->countByAttributes(array(
        'entryId' => $entry->id
    ));

    $entry->enabled = ($purchaseCount != 0);
}

Last but not least, you will need to update your entry purchase form to record the entry ID being purchased. We’ll do that as an option on the line item.

(If you look at the onOrderComplete function, we’re actually combing through the purchased order’s line items to look for these entryId options. This is where it gets set.)

<form method="POST">
    <input type="hidden" name="action" value="commerce/cart/updateCart">
    <input type="hidden" name="redirect" value="commerce/cart">
    <input type="hidden" name="qty" value="1">
    <input type="hidden" name="purchasableId" value="{{ variant.purchasableId }}">

    <!-- Associate the line item with this entry ID -->
    <input type="hidden" name="options[entryId]" value="{{ entry.id }}">

    <input type="submit" value="Buy Now">
</form>

Baring any typos, that should do it!


How do I apply taxes to subscriptions with Stripe plugin?

I realise this is a bit of an old question, but I was faced with the same problem recently so I thought I'd document my solution here for anyone in the future that comes along needing to apply tax to a subscription in Craft Commerce.
There are two problems here:

Subscriptions aren't purchasables in Commerce at the moment, so they can't be added to a cart and have tax rates applied to them in the same way that you would with 'normal' products.
Subscription pricing is determined by Stripe rather than internally in Commerce, and the same is true of tax rates. There's no way of syncing or importing tax rates defined in Stripe into Commerce.

As far as I know, there is no out-of-the-box method in Commerce to apply tax to subscriptions automatically. It requires either manually adjusting subscription invoices within Stripe, or programatically adding a tax rate to a subscription before it's sent to Stripe. I chose the latter method.
Showing a bill before payment
I solved this by creating a single 'Subscription' product within Commerce, and then creating a number of variants on this product to represent the various subscriptions that I had defined in Stripe, including setting the prices to match those that are defined in Stripe. I added a custom field called subscriptionPlanHandle to the variant config to hold the handle of the subscription plan (handles for subscriptions are found in Commerce > System Settings > Subscription Plans), to allow me to fetch the correct subscription plan when creating the payment page.
Next, I set up a tax rate in Commerce, in my case VAT. I then set this tax rate to be applied to my subscription products - this can be done in Commerce > System Settings > Product Types and then edit the product type to set its Available Tax Categories (under the Tax & Shipping tab) to the relevant tax rate.
I then used the standard 'cart' approach to my purchase journey, showing my subscription products on a product page and allowing one to be added to the cart. A summary of the pricing was shown by looping through the contents of the cart and showing line item pricing followed by the tax adjustment and then a total:
{% set cart = craft.commerce.carts.cart %}

{% for item in cart.lineItems %}
    {% set itemsSubtotal = itemsSubtotal + item.subtotal %}

{{ item.description }}

{{ item.subtotal|commerceCurrency(cart.currency, stripZeros=true) }}

{% endfor %}

{% set totalPrice = itemsSubtotal %}

{% if cart.adjustments|length %}

Total

    {% for adjustment in cart.orderAdjustments %}
        {% set totalPrice = totalPrice + adjustment.amount %}

Excl. {{ adjustment.name }}: {{ itemsSubtotal|commerceCurrency(cart.currency, stripZeros=true) }}

Incl. {{ adjustment.name }}: {{ totalPrice|commerceCurrency(cart.currency, stripZeros=true) }}

    {% endfor %}
{% else %}

{{ totalPrice|commerceCurrency(cart.currency) }}

{% endif %}

Now, since subscriptions aren't purchasables in Commerce (yet), you can't just go through the normal checkout since the subscriptions won't be sent to Stripe. On the payment page/section, you have to do some juggling about to get the subscription plan UID from the product(s) in the cart and then create the appropriate payment form. Here's how I solved it:
<form method="post" accept-charset="UTF-8" novalidate>

    {{ csrfInput() }}
    {{ actionInput('commerce/subscriptions/subscribe') }}

    {% for item in cart.lineItems %}
        {% set variant = craft.variants().id(item.purchasableId).one() %}
        {% set plan = craft.commerce.getPlans().getPlanByHandle(variant.subscriptionPlanHandle) %}

        {{ plan.getGateway().getPaymentFormHtml({})|raw }}

        <input type="hidden" name="planUid" value="{{ plan.uid|hash }}">
    {% endfor %}

    <button type="submit">Pay</button>

</form>

This fetches the variant using the the item.purchasableId property, and then fetches the matching subscription plan using the custom subscriptionPlanHandle field mentioned above. A hidden field is then added to the form with the value of the plan's UID. The form can then be submitted to the subscription controller to set up the subscription.
Applying tax to a subscription
My solution requires either a custom module or plugin, so that you can listen to the EVENT_BEFORE_SUBSCRIBE event triggered by the Stripe gateway and modify the individual subscription item to add a tax code.
The steps to get this work are as follows:

In your Stripe account, you need to define a tax rate. You can do this by going to Billing > Tax rates in your Stripe dashboard, clicking 'New' and creating a new tax rate. In my case, I needed to apply VAT so I created a tax with a rate of 20%, named it 'VAT' and saved it. Next, you need to grab the ID of your new tax rate. Copy this to your clipboard - you'll need it in the next step.
Back in Commerce, find the appropriate tax rate in Commerce > Tax > Tax Rates. Paste the Stripe tax ID into the 'Code' field in Commerce. In my case, I turned on the 'Don’t apply this tax when the address has a valid VAT ID' option, as a simple way to identify that this rate was a VAT rate.
In your custom module or plugin, add an event handler in the main plugin file. This can either be directly in the init method or you could have a separate method to apply all of your event handlers that you invoke from the init method.

Here's the event handler code:
Event::on(
    StripeGateway::class,
    StripeGateway::EVENT_BEFORE_SUBSCRIBE,
    function(SubscriptionRequestEvent $event) {
        $taxRates = Commerce::getInstance()->getTaxRates()->getAllTaxRates();

        foreach ($taxRates as $taxRate) {
            if ($taxRate->isVat) {
                $event->parameters['items'][0]['tax_rates'] = [$taxRate->code];
            }
        }
    }
);

This event is triggered before a subscription is sent to Stripe, and allows you to modify the parameters that are sent to Stripe - like, say, to add in a tax rate!
The code inside the event handler gets all of the tax rates, then loops through each one until it finds one whose isVat property is set. It then adds a new tax_rates property to the first item in the items array (which should only have one property beforehand - the planId), and sets its value to an array containing the value of the code property from the tax rate.
Using the code property to hold the ID of the Stripe tax rate allows this data to be content-managed in Commerce, so that you can swap between test data and live data easily without requiring a code change. I'm not sure if there's another use for the code property within Commerce, but this worked for me.
This method is reasonably robust if you only need to apply a single tax rate like VAT, but if you need to charge lots of different tax rates it would need some modification to ensure the right tax rate is applied.
Note: these code examples don't deal with determining whether the VAT rate should be applied; you'll need to make sure that the VAT is only applied in the appropriate countries depending on the country set in the customer's shipping address.
Tidying up afterwards
This process should hopefully leave you with an active subscription in Stripe with the correct tax rate applied, but also an unfinished order since the subscription controller doesn't use the cart at all. I chose to handle this by listening to the EVENT_AFTER_CREATE_SUBSCRIPTION event and deleting the cart directly once the subscription was created.


The query returned by buildElementsQuery() is already prepped to fetch unique entries. But it’s possible for two distinct entries to have the same title, which is why it may look like duplicate entries are being returned.

To only fetch entries with unique titles, do this:

$query->group('content.title');


Why are PNG images bigger in file size on the (S3) server?

I agree with Brad's comment, this is very similar to those two other threads.

That being said, here is an important quote which is buried on one of those threads...

  When an image is first uploaded, Craft will "sanitize" the image for any malicious code by re-saving the image out to a new file. It jumps through some pretty significant to ensure that the sanitized image is as close to possible as the originally uploaded image in both quality and file size, which usually explains the differences people see in file sizes.

I believe this is what the OP is experiencing.


You can disable the token for a certain controller via

use Craft;
...
Yii::$app->controller->enableCsrfValidation = false;

or inside a Controller for a certain request

/**
 * @inheritdoc
 */
public function beforeAction($action)
{
    if ($action->id == 'my-method') {
        $this->enableCsrfValidation = false;
    }

    return parent::beforeAction($action);
}

Take a look at $enableCsrfValidation property of yii\web\Controller.


I'm not totally sure I fully understand your question, but what you're describing definitely sounds like a job for Matrix.

Unfortunately I have no experience with Silverstripe, so I can't make any comparisons to Craft or Matrix and similar functionality in that system, but as a basic overview of what Matrix is and does, I'll just quote the official docs:

  Matrix fields allow you to create multiple blocks of content within a single field.

Basically, you can think of a Matrix field as a glorified table of repeating content. If you ever worked with WordPress and Advanced Custom Fields, Matrix is basically the same thing as the Flexible Content field in ACF.

Matrix fields have many use cases, but using them as "layout" builders in modular design is very common, and is (as far as I can tell) what you're looking to achieve here.

A block type in a Matrix field is basically a self contained set of fields. A block is an instance of a block type. After configuring a Matrix field with a selection of different block types (or layouts) such as a WYSYWIG editor, an image gallery, an embedded video, a news feed etc. When a user is editing the entry, he or she can add one or several blocks of each type to the entry, in any order.

For your use case (such as I understand it) let's say you create a Matrix field with the handle pageLayout, and add the following block types to it:

Advert (handle advert)
Customer list (handle customerList)
Text and image (handle textAndImage)

For each block type, you add the fields you need. Since the block types are sandboxed, you can have a field with the same handles in more than one block type, e.g. an image field called image or a text field called text in both the advert and textAndImage blocks.

It's difficult to advise on specific fields you'd need for the three block types above, but for your advert block type you might need a Plain Text field for URL and an Assets field called image. Assuming your customers are Users or even Entries you might need a Users or Entries field for your customerList block type, and the textAndImage field should probably have a Rich Text and an Assets field. You also might want to give the content editor the option to add a custom heading to each block, in which case you could add a PlainText heading field to each block type.

When you edit your entries, you can create one or several of each of the three block types. You can reorder blocks you already created, remove single blocks or add new blocks of either type above or below existing blocks.

To render your Matrix content, you'll usually work with a Twig for loop to run through all your blocks and render their data.

Using the {% switch %} tag to render different code based on the block type is a good way to keep things readable and clean – here's an example where all the individual block type markup is inline:

{% for block in entry.pageLayout %}
    {# Inside here, `block` refers to a single block in the Matrix field #}
    {% switch block.type %}
        {% case 'advert' %}

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

        {% case 'customerList' %}

                {% set customers = block.customers %}
                {% for customer in customers %}

{{ customer.name }}

                {% endfor %}

        {% case 'textAndImage' %}
           {% set image = block.image.first() %}

{{ block.text }}

    {% endswitch %}
{% endfor %}

Of course, to keep things even more tidy, you might opt for an approach using template partials, where you put the markup for each block type in their own template (e.g. templates/blocks/advert.html), and use the {% include %} tag to render them inside the Matrix for loop:

{% for block in entry.pageLayout %}
    {% switch block.type %}
        {% case 'advert' %}
            {% include 'blocks/advert' %}
        {% case 'customerList' %}
            {% include 'blocks/customerList' %}
        {% case 'textAndImage' %}
           {% include 'blocks/textAndImage' %}
    {% endswitch %}
{% endfor %}

In fact, if you name your templates after your block type handles, you may get away with not having a {% switch %} tag at all:

{% for block in entry.pageLayout %}
    {% include 'blocks/'~block.type %}
{% endfor %}


If you're looking to get the locale code for each site's language globally, it'd be something like this:

{% for locale in craft.i18n.getSiteLocales() %}
    {{ locale }}
{% endfor %}

If you're in the context of an entry, and you want to get the full URL and locale code for each site that entry is enabled it, it'd be similar to the answer here: https://craftcms.stackexchange.com/a/23751/57

{# Grab the entry #}
{% set entry = craft.entries.id(2).one() %}

{# loop through all of the supported sites for the entry #}
{% for siteInGroup in entry.getSupportedSites() %}
    {% set site = craft.app.sites.getSiteById(siteInGroup['siteId']) %}

    {# Grab the entry for the given site #}
    {% set entryForSite = craft.entries.id(entry.id).siteId(site.id).one() %}

    {# output the site-specific entry info #}
    <link rel="alternate" href="{{ entryForSite.url }}" hreflang="{{ site.language }}">{{ entryForSite.title }}</link>
{% endfor %}


After discussing it with the team we worked out that deleting the plugin directory from the /vendors folder and rerunning composer install resolved it. Not sure why though...


Craft login problem with memcache and ubuntu?

I saw a few work arounds for this here, hopefully it helps:
https://github.com/yiisoft/yii/issues/2376


I guess with Redactor II you "manually" have to make sure you cannot create those tags with buttons/shortcuts or by pasting in rich text.

Button configuration works with the formatting and formattingAdd settings.
Paste config settings were added with Redactor II 1.2 (Craft 2.bla), the ones you're probably interested in are pasteBlockTags and pasteInlineTags.

Redactor II deprecated the paragraphize setting and automatically wraps each paragraph in <p> tags. If you also want to prevent <p> tags, removing them on a template level using a Twig filter like striptags is probably your best bet at the moment (→ see Redactor II Craft 2.5 Prevent Paragraphs).


"Craft is unable to determine if an update is available at this time."

You'll get this if (for any reason) your local install can't connect to our web service that holds all of our update and release information.

If this happens, your local install will cache that there was a connection error and cache to not try again for 5 minutes, no matter how many times you refresh.

So you can either wait the 5 minutes and try again, or clear your data caches under Settings->Tools->Clear Caches Tool and try again and hopefully the connection problem will have resolved itself.

You can also check your craft/storage/runtime/logs files for any cURL related errors indicating a cURL configuration problem on the box.


UsersController's actionUploadUserPhoto and actionCropUserPhoto with Element API

Not natively.  The Element API plugin provides a "read only" API to Craft's controller endpoints.  Both actionUploadUserPhoto and actionCropUserPhoto request POST/write requests.

You could fork it and add POST/write functionality to the plugin/API, though.


Using Craft CMS to manage content within an app

Several people are using Craft to power apps.

Here's a good hangout: Craft Powered Apps, with Aaron Berkowitz discussing how PBS Kids uses Craft to power multiple apps, by making the data in Craft available to the apps available via a JSON API. I believe they use Cordova, which runs independently of Craft but grabs all the data for the app via the API.

Aaron also discusses how publishing content via Craft helps them get around some app-update requirements.


In one of my plugins I inject a little bit of javascript that polls Craft.cp.runningTaskInfo for changes to detect if a task is finished.


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

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

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

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

    next
    previous

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


Bug with non-ascii characters, quotes and OR operator in search?

This looks like a bug to me too. Here are the search terms and generated queries:

'pølser OR pålegg' -
   SELECT * FROM `craft_searchindex` WHERE (MATCH(`keywords`) AGAINST('pølser palegg' IN BOOLEAN MODE)) AND `elementId` IN (3,18,21,22,23,24)

'"pølser" OR "pålegg"' -
   SELECT * FROM `craft_searchindex` WHERE (`keywords` LIKE '% pølser or %') AND MATCH(`keywords`) AGAINST('+palegg' IN BOOLEAN MODE) AND `elementId` IN (3,18,21,22,23,24)

'"egg" OR "spekemat"' -
   SELECT * FROM `craft_searchindex` WHERE ((`keywords` LIKE '% egg %') OR MATCH(`keywords`) AGAINST('spekemat' IN BOOLEAN MODE)) AND `elementId` IN (3,18,21,22,23,24)


Displaying image from related CraftCommerce entry

Ok first thing take the s off relatedProduct because each loop is over one relatedProduct ;) - then you can do something like this:

{% for relatedProduct in product.relatedAccessories %}
   {{ relatedProduct.title }} - {{ relatedProduct.accessoryDescription }}
   Url: {{ relatedProduct.yourAssetHandle.first().url }}
{% endfor %}

You should probably protect that by first checking {% if relatedProduct.yourAssetHandle.first()|length %} unless you can be completely certain you will have an asset (required field for example).


Entry Form doesn't save the entry and goes to 404 page

Right, the issues was that there was a validation error on a field, but the form didn't reload and display those errors, it just went to a 404 page.


Smart Map plugin - Get visitor's lat/lng

Smart Map can indeed do this! It's currently an undocumented feature, because I wasn't sure if/how it was going to evolve over time. However, that feature has changed very little over the past two years, so perhaps it's time to finally document it. :)
UPDATE: As of Smart Map 2.3, this is now a publicly documented feature.


Upgrading site from 2.3.2636 to 2.4.2684

Probably a timeout on the MySQL side. You could try making a database backup manually and then changing this config value to false before trying the update again: http://buildwithcraft.com/docs/config-settings#backupDbOnUpdate

That way Craft will skip the database backup during the update, saving some time and hopefully preventing a timeout. Just remember to make a backup every time you update from then on though.


How to allow data attr in tags in Redactor HTML Purifer

See this config setting: http://htmlpurifier.org/live/configdoc/plain.html#HTML.AllowedAttributes

You should be able to use it to allow data attributes.


You have named the file feed.rss, and you are trying to access it by going to /rss. So I can see two issues here:

The template file needs to be either .html or .twig, as per the
tutorial you have referenced
The name of the template file will dictate the URL for that template. If you re-name your template file to feed.twig, you access that template by going to /feed


Pass URL parameter through General Config file

I think I figured out how to do it but I'd like to get any opinions on this matter.

Right now I've setup a dummy template which contains a redirect to the URL with the parameter I need. So:

'activateAccountSuccessPath' => 'members/activated

And then that template contains:

{% redirect 'members/profile?activated=true' %}

This is working great. And I guess it's a clean way to do it from the point of view that each variable in the config file has a different target. But is it "cool" to do a redirect just for that?


5th line: category.videoLink|length%}
Could you try to insert a space between "length" and "%"?


It may not be suitable for your use case but you could use an Asset query to fetch assets related to your entry:

{% set assets = craft
    .assets()
    .withTransforms(['eventImage'])
    .relatedTo({
        sourceElement: entry,
        field: ['your','fields']
    })
    .all() %}

{% for asset in assets %}
...
{% endfor %}

(If these are your only asset fields on the entry, you don't need field: ['your','fields'])


Have you tried putting da_dk in as the key in the siteUrl array?


Use url segment as querystring parameter [Craft 3]

You need to define routes for these URLs in settings in the CP or via the config/routes.php file.

return [
    'team/<regionId:[^\/]+>' => ['template' => 'team/_index'],
    'pricing/<regionId:[^\/]+>' => ['template' => 'pricing/_index'],
];

By defining the named subpattern, the template will get loaded with a regionId variable defined.
Use the is defined test or the null-coalescing operator to see if the template got loaded via your custom route or via the entry route. In the case that the template gets loaded via the custom route you also need to define the entry variable manually, null-coalescing operator again allows you to do that quite elegantly.

{% set entry = entry ?? craft.entries.section('pricing').one() %}
{% set regionId = regionId ?? 'en' %}


Problem with Adjuster plugin Class not found

carbonBalanceAdjuster.php should be CarbonBalanceAdjuster.php since the name of the class is CarbonBalanceAdjuster and you're probably on a case-sensitive file system, which is why auto-loading can't find it.

The same goes for your other plugin files as well.  You can use https://pluginfactory.io to generate boilerplate plugin code to help avoid case-sensitivity issues like this.


Under Settings > Sections > [section] > Site Settings, you can set the Default Status per-site for new entries in that section.

For copying the actual content, set the appropriate "Propagation Method" setting underneath. Note that the propagation only happens on the first save. If you need to overwrite/sync content across sites after the first save, there's the Sync Sites plugin: https://github.com/timkelty/craftcms-site-sync


The above isn't too clear, but what I was trying to do is use different templates for  different category landing pages. It works with the following:

{% switch category.slug %}
    {% case 'features' %}
        {% include 'categories/_features.html' %}
    {% case 'news' %}
        {% include 'categories/_news.html' %}
    {% default %}
        {% include 'categories/_news.html' %}
{% endswitch %}


Here's a plugin I made that does just that:

https://github.com/khalwat/minify


Entry Post Date Format time since - X days ago

It looks as though Craft 3’s built-in duration Twig filter might help:

Posted {{ entry.myDateField.diff(now) | duration }} ago.

With a bit of additional logic, you can make this more useful, after an Entry leaves a specified window:

{% set dateOneYearAgo = now.modify('- 1 year') %}
{% set dateOneMonthAgo = now.modify('- 1 month') %}
{% set dateOneDayAgo = now.modify('- 1 day') %}

{% set elapsedMonths = entry.myDateField.diff(now).m %}
{% set elapsedDays = entry.myDateField.diff(now).d %}

{% if entry.myDateField < dateOneYearAgo %}
    {# Posted longer ago than one year... #}
    Posted on {{ entry.myDateField | date('M j, Y') %}
{% elseif entry.myDateField < dateOneMonthAgo %}
    {# Posted longer ago than one month (but more recently than one year, as we caught that, above)... #}
    Posted {{ elapsedMonths }} month{{ elapsedMonths != 1 ? 's' : '' }} ago
{% elseif entry.myDateField < dateOneDayAgo %}
    {# Posted longer ago than one day (but, as above, more recently than a month ago)... #}
    Posted {{ elapsedDays }} day{{ elapsedDays != 1 ? 's' : '' }} ago
{% else %}
    Posted {{ entry.myDateField.diff(now) | duration }} ago.
{% endif %}

The if statements compare the date objects, and returns true if entry.myDateField is earlier than the date one year ago (- 1 year), one month ago (-1 month), etc.

now.modify(…) is a convenient and human-readable way of getting a date relative to the current time—you can pass this method any relative date string.

The ternary statements (like {{ elapsedDays != 1 ? 's' : '' }}) are just a crummy way of properly pluralizing the units of time—I'd recommend using the Typogrify plugin, instead, as it offers some more declarative ways to handling this— say, {{ 'month' | pluralize(elapsedDays) }}.

  Note: I've omitted special circumstances for things like “yesterday,” as these constraints can be layered in as new else if statements—just be sure to put the tightest constraints at the top, so that it matches your priorities (i.e. a test for “last week” should come after a test for “yesterday”). Anything you don't care about can fall through to the default duration filter.


How to correctly format API requests for Mandrill using Fetch plugin? Getting error "you must specify a key value"

Two things I'm noticing about your code snippet:

You'll want to use POST per the Mandrill API docs.

  All API calls should be made with HTTP POST.

The options object should only contain valid Guzzle request options (key is not an actual request option); I think what you're trying to do is pass your key parameter in the request body. There are multiple options for sending data in the request body (form_params, body, json, or multipart), but since the Mandrill API is expecting a json request body we'll use the json option like so:

{% set options = {
  json: {
    key: 'REDACTED',
  }
} %}

All together, this should give you a working API call:

{% set client = {
  base_uri: 'https://mandrillapp.com/api/1.0/',
  timeout: 10
} %}

{% set options = {
  json: {
    key: 'REDACTED',
  }
} %}

{% set destination = 'users/ping.json' %}

{% set request = fetch(client, 'POST', destination, options) %}


Event Listener for Publishing Scheduled Posts

There isn't an event that fires when an entry with a future post date goes live, since it's just compared against the existing time and there's no guarantee that any PHP will be executing at that exact time.

You could write a cron job that hits a plugin's controller that checks every minute or so for any entries about to go live.

Or maybe adopt something similar to this for your Redis/full page caching solution.


This was a ModSecurity rule tripping up the request and causing an infinite redirect loop.

I don't know which rule it was exactly, but disabling ModSecurity resolved the issue.


Maybe this is what you are looking for

  When the deleteFilesAndFoldersInVolume permission is not set, the user cannot edit the image. And dragging files into other folders result in an error.


Where can I set how the pagination links render?

Delete the overridden pageTrigger config setting in your config/general.php file:
https://docs.craftcms.com/v3/config/config-settings.html#pagetrigger


SuperSort `rsortAs` error with `postDate`

Figured it out, needed to format the postDate object accordingly:

{% set products = products | supersort('rsortAs', '{ postDate | date("U") }') %}


Placing an extra empty linebreak in the Redactor Field


In entries query, is there a way to check if matrix block is used?

In this specific case, yes. You can filter your entry query by whether a specific matrix field has at least one block like so:

{% set query = craft.entries({
    section: 'blog',
    myMatrixField: ':notempty:',
    limit: 10
}) %}

or for fields that have 0 matrix blocks in the specific field:

{% set query = craft.entries({
    section: 'blog',
    myMatrixField: ':empty:',
    limit: 10
}) %}

However these are the only two values available for this specific field type. You cannot, for example, search for entries with 3 or more blocks.


From Twig, this seems like a decent solution.

Could possibly be streamlined a bit if you wanted to do it from PHP, but as long as you're not dealing with large amounts of images, it's probably not worth it.


Per the Modules vs. Plugins docs, only plugins get their own migration track. Modules are considered part of the project (like templates and config files), so if there are any DB changes that need to be made for the module to run, those changes should be made via content migrations.

If the module is meant to be reused across multiple projects and does require DB migrations, then it will be better off as a plugin.


Clear template cache after update sale on Craft Commerce

More than likely the issue is not the prices not updating, but the sale conditions as Luke mentioned.

In theory, Craft will automatically clear template caches when an element within the cached region is updated (note one trap is this process of deleting stale template caches runs as a job task, so may not happen absolutely immediately...give things 30 seconds or so before you check them).

If things don't seem to be working for whatever reason, you can clear caches manually using the Craft control panel.

Thus, in case it is somehow cache related:

Craft 2: Control panel -> settings -> clear caches

Craft 3:

There are now console commands to clear caches (run ./craft on its own and it will list all of the available commands e.g. ./craft clear-caches/template-caches

Or, you can of course still use the control panel-> utilities -> clear caches


Execution timeout problem when trying to add new field

Some common steps to find the culprit.

Always work in dev mode
Enable Debug Toolbar or read the brief tutorial by nystudio107
Disable all the custom plugins one-by-one.
Once development is done, switch to production mode and disable log.
Adjust Mysql and Server minimum configuration based on your site load.
There is no need to use multiple cache strategy.
Activate useful admin dashboard widget only.
On the entries page, activate the most useful Table Columns only.

Check system report information in the dashboard, make sure all the suggested requirements are fulfilled.


CDbException warning 1265 after updating matrix field

The column field_testimonial_quotation in your craft_matrixcontent_testimonialmatrix table has data in it that is longer than 145 characters long.

Since it looks like your MySQL box is running in strict mode, MySQL is warning you that data has been/will be truncated by changing the max length to something below that.


"Object of class Craft\ElementCriteriaModel could not be converted to string" in Craft CP

This was caused by an incorrectly configured assets field in the entry type. The upload location had an invalid variable set in the path.


This could be a couple things:

Server config
.htaccess file
SSL Certificate

But it sounds to me like the insecure login button means those assets are not being served over SSL. How'd you confirm the site is served over https?

Craft's control panel resources are not actually in the document root so what's happening is Craft's controller (index.php) is handling those would-be 404 requests and spitting out the cp resource in question from the backend via php.

Server Config

If you can access a static file over https in the document root (say something like https://yoursite.com/images/sitelogo.png or your main CSS file) and your browser is showing the padlock and not an error, that means your virtual host is setup correctly.

That's the first thing I'd rule out. If you're not getting your browser's padlock on a simple request like that, your SSL setup needs tweaking, probably a bad virtual host config. For good measure, most certs allow www- and non www so check www.yoursite.com as well. (It's easy to forget to put in a ServerAlias in the VirtualHost block to handle both hostnames and then try to access the site and wonder what's going on, I've done it!)

.htaccess

Another source of trouble could be if you have some additional rewrite rules in your .htaccess file. A common one is to rewrite from www.sitename.com to sitename.com or vice versa for example—that could actually be redirecting to the insecure resource instead of over SSL, depending on your rewrite rules. So Craft wouldn't actually be serving your site over SSL because your rules would always say to rewrite the request to an insecure resource.

SSL Certificate

Browsers can do weird things if you your SSL cert is not installed correctly.  I like Symantec's SSL checker for this sort of thing. If you're using domain based validation, like the regular comodo or geotrust certs, some of them require additional "chained" or intermediate certificates to work correctly. Besides checking your server config and certificate, that checker will also make sure the chain of trust is in the right "order".


Proper order of multi-environment config

In my experience, the order does matter. The array is read in order from top to bottom testing the domain for a match against each criteria (key). If there's a match, that array of settings is used and continues down the list which can possibly overwrite variables that were previously set.

For example, in this configuration...

// Development
'dev.mywebsite.com' => array(
    'database' => 'dev_mywebsite',
),
// Production
'mywebsite.com' => array(
    'database' => 'prod_mywebsite',
),

Your development site http://dev.mywebsite.com will be matched twice, once with the full url dev.mywebsite.com and second as a partial match for mywebsite.com. The second match will overwrite the database setting and your dev site won't load properly.

The Craft documentation example uses the domain criteria of '.com' and '.dev' with '.com' coming after '.dev'. That works fine because example.com will never partially match example.dev.

The "Foolproof Multi-Environment Config" from Craft Cookbook works by matching specific server name local.domainname.com or stage.domainname.com first and using a the production environment as a fallback.

Similarly, you could use the config order to your advantage and only change settings as they're needed. The '*' array can be used as a default/fallback environment.

For example:

// Default environment: Production
'*' => array(
    'tablePrefix' => 'craft',
    'server'   => 'localhost',
    'user'     => 'xxxxxxxx',
    'password' => 'xxxxxxxx',
    'database' => 'prod_mywebsite',
),
// Development
'dev.' => array(
    'user'     => 'xxxxxxxx',
    'password' => 'xxxxxxxx',
    'database' => 'dev_mywebsite',
),

Notice this setup doesn't change the server setting since the dev environment also uses localhost.

Also, I've seen setups where the fallback settings are the Development or Local instead of Production. The advantage there is that your Production
site data would be protected from errors in your config file. I've actually made a mistake where the staging server domain didn't match the config file and changes from the staging server were happening to the Production database (bad!) because it was the fallback.

Here's an example from Focus Lab's EE Master Config for ExpressionEngine:
https://github.com/focuslabllc/ee-master-config/blob/master/config/config.env.php

As a side note, the "Foolproof Multi-Environment Config" could probably use the strtolower() function on the 'HTTP_HOST' variable as Bjørn Børresen points out in a commit message in the EE Master Config.

switch (strtolower($_SERVER['HTTP_HOST']))

  HTTP_HOST should be made lowercase as one cannot guarantee that it always is (most browsers do this, but not all) - in which case the wrong config will be loaded


Maximum execution time exceeded when adding or updating plugins from the Control Panel

You need to figure out where your PHP config file is located (php.ini) and increase the value for the max_execution_time setting.

The best way to locate your php.ini:

If you can run php from the command line, run php --ini. Alternatively you could use php -i | grep 'Configuration File' to search the full phpinfo(). More info...
If php isn't accessible via the CLI, you can also create a simple php file that contains the following snippet. Load it up in your browser and search the page for "Configuration File". This will give you the location of your php.ini.

<?php

phpinfo();

Other options:

If you're using a Laravel Valet / Homebrew setup, the php.ini file is located at /usr/local/etc/php/X.X/php.ini where X.X is your PHP version number.
If you're running MAMP Pro, I believe they provide a built in editor to customize this - see How do you change php.ini values in MAMP Pro?


Error after Freeform Pro update to 3.5.10

You'll need to update to Freeform 3.6+ (Craft 3.4+), which contains a compatibility fix for this issue. :)

https://docs.solspace.com/craft/freeform/v3/setup/changelog.html#_3-6-0-2020-01-23


Can user group permissions be used to override entry section locale settings?

Is it possible to override a section’s settings based on user group permissions?

There's nothing native in Craft that would allow you to do this.

Maybe you could do something like write a plugin that listened to the onBeforeSaveEntry event and simulate it by enabling/disabling it for various locales based on the current user's permissions.


MySQL has a hard coded limit of 4,096 columns per table, although that can be effectively limited by the data types of columns involved.

Matrix fields get their own tables, so they don't count against the craft_content table.

But yes... if you're planning on having non-Matrix fields in the 2,000 - 4,000 field range, then there's a chance you'll bump into MySQL limitations.


Product category not being added to the order model. Craft Commerce

I never used Craft Commerce but you usually store relations (no matter which) with the id - not the title. So I expect the Commerce plugin will only recognize your category with this html

 <select id="chocOptions" name="fields[chocolateOptions][]" class="options">
      <option title="selectOption">Select Option</option>
      {% for category in craft.categories.group('chocolate') %}
           <option value="{{ category.id }}">{{ category.title }}</option>
      {% endfor %}
 </select>

And you have to name your field correctly like statet here

Edit
The easiest way to get to know how you have to build your html is the following

open the form in your Craft CP
Right click on the field
Click on "inspect" or "inspect element" or something like this
Search for the input or a hidden input. When I inspect a normal relation field it looks like this

    <input type="hidden" name="fields[relation][]" value="13">

        Some Name


Never used craftman before, but it looks like the database name it creates is called craft and it's pulling the database user and password from some environment variables named CRAFT_DB_USER and CRAFT_DB_PASSWORD you could check for.


Is it possible to reassign an existing event from one Solspace Calendar to another ?

This currently isn't built into Calendar, but if your calendars use the same fields, you should be able to manually adjust the calendarID column in the craft_calendar_events database table. Otherwise, you'll have to delete the event and create it again for the correct calendar.

Sometime in the future we plan on seeing if we can add the option to allow changing of calendars. The issue for us is that each calendar is able to have a different field layout and tabs, etc, so it complicates things. :)


Wrong urls printed for small subset using getNext and getPrev

I believe I already answered this in the OP's other, similar question, but:

You shouldn't pass a string value (i.e. 'posts') to getNext() and getPrev() – those methods expect either an ElementCriteriaModel instance, or an object with attributes representing a query (i.e. something like { section: 'posts' }.

What actually happens when you call entry.getPrev('posts'), is that Craft will just ignore the string value (I'm guessing 'posts' is a section handle, but there's no way for Craft to know that), and you're probably going to get an EntryModel back, but it won't reliably be from the same section as your current entry – it can be an entry from any section in your system, which is probably where your problem is.

So here's how your code should probably look:

{% set criteria = { section: 'posts' } %}
{% set prev = entry.getPrev(criteria) %}
{% set next = entry.getNext(criteria) %}

You can also include other attributes, like for example order (otherwise, default attributes will apply, such as postDate desc for a Channel section, or structure for a Structure):

{% set criteria = { section: 'posts', order: 'title asc' } %}
{% set prev = entry.getPrev(criteria) %}
...

...and of course, you can make the criteria dynamic:

{% set criteria = { section: entry.section } %}
{% set prev = entry.getPrev(criteria) %}
...

Finally, make sure to always wrap the returned values from getNext() and getPrev() in a conditional – you can't always be sure that there'll be a valid "next" or "previous" element for any given entry, so this avoids template errors:

{% set prev = entry.getPrev(criteria) %}
...
{% if prev %}
    {{ prev.title }}
{% endif %}

Of course, it's possible to declare a fallback value whenever there isn't a next or previous element:

{% set next = entry.getNext(criteria) ?? craft.entries(criteria).first() %}


File robots.txt needed in Craft package?

The specific directive to disallow the /craft/ directory isn't necessary if your craft folder is below the webroot.

However, it's good practice to have a robots.txt for each site, so I don't recommend deleting it altogether. You can change the directives to fit whatever robots criteria you need for your site. (For example, if you launch a beta site, you'd want to Disallow the whole thing to avoid duplicate content penalties.)