composer update missing zip extension (ext-zip) on MacOS

The reason seems to be that either the PHP version of the MacOS Catalina update or a version installed via brew do not come bundled with the ext-zip extension.

You can verify that by calling php -m in the Terminal. You will get a list of all modules and it will not contain the word zip

Even if it contains the word zip it does not necessarily mean that composer has it available. This is caused by the way ZSH (shell on MacOS) handles the PATH variable.

In my case I used an alias pointing to the MAMP version of PHP (which has zip enabled), but composer was using the PHP version found in the PATH variable.

Solution for me: Since I am using MAMP I modified the PATH in /etc/paths to have the MAMP PHP PATH on the very beginning, e.g.

/Applications/MAMP/bin/php/php7.1.31/bin
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin

After that change composer update should work again as expected (make sure you close your Terminal first and do the update in a new Terminal window). Also php -m should now definitely list the zip extension


Well, a custom field actually does sound like the perfect solution. It's easy and consistent to check on all outputs and areas (sitemap/menu's/other navigations).


What's the best way to degrade gracefully when using a Plugin Variable?

I think the best way to do this would be in your PluginHandleVariable file's method, just have it accept one, optional parameter and expect it to be an array.

public function variableMethod($options = null)
{
    if (!$options || !is_array($options))
    {
        return "No options set";
    }

    // Now you can check for individual options on the array
    if (isset($options['option1'])
    {
        ....
    }

}

Then both of these would work:

if craft.pluginname.variable()
if craft.pluginname.variable(options)


Product Combination Discount in Commerce 2?

Indeed, the way to go is setting up a module or plugin for this sort of thing. While I did get that working in practice, I still have questions regarding how one can loop through and compare using the Craft CMS 3 Commerce 2 APIs to actually apply the discount based on custom fields on the variants. That will be a separate question entirely.

If you stumble upon this issue, the starting point I used was this;
https://github.com/oof-bar/commerce-example-adjuster

Here's a link to the new question


Generating pending image transforms stuck

I was having this issue (w/ PHP 5.6, Craft 2.6.x, on WebFaction hosting) because it seemed like PHP had no memory limit and single processes were handling huge image transform queues, bombing when it got over 1.5gb or so.

Making sure Imagick has a memory cap seems to do the trick to avoid the queue getting stuck as PHP runs out of memory, which is discussed here:

Possible memory leak - GeneratePendingTransforms/ImageMagick

Relevant code:

// From http://stackoverflow.com/a/12835966
// Pixel cache max size
$this->setResourceLimit(\Imagick::RESOURCETYPE_MEMORY, 256);
// Maximum amount of memory map to allocate for the pixel cache
$this->setResourceLimit(\Imagick::RESOURCETYPE_MAP, 256);

in craft/app/vendor/pixelandtonic/imagine/lib/Imagine/Imagick/Imagick.php at line 33, at top of smartResize() function.

Update:

If you are not on shared hosting but on a VPS (or otherwise have sudo access on your server, OR are able install ImageMagick + php-imagick from source), you can set memory caps for ImageMagick directly using a policy.xml file, e.g.:

<policy domain="resource" name="memory" value="1GiB"/>
<policy domain="resource" name="map" value="1GiB"/>
<policy domain="resource" name="area" value="1GB"/>
<policy domain="resource" name="file" value="768"/>


I suggest you to read about the Yii Query Builder

craft()->db->createCommand()
    ->insert('mytablename', array(
        'field1'    => 'foo',
        'field2'    => 'bar'
    ));

Or you can use Active Records in Craft

$record = new Record();
$record->field1 = 'foo';
$record->field2 = 'bar';
$record->save();

Or you can use Craft Elements (entries/categories/tags)

$entry = new EntryModel();
$attributes = [
   'section'   => $yourSectionId,
   'entryType' => $yourEntryTypeId,
   'field1'    => 'foo',
   'field2'    => 'bar'
];
$entry->getContent()->setAttributes($attributes);
craft()->entries()->saveEntry($entry);


What is the correct way to include jQuery and jQuery UI in Craft?

You would use <script> tags in your template, preferable in a _layout.html or _base.html template which you extend from all your other templates.


Filter entries in the CP based on custom permission

After some digging I came up with some answers myself. For future reference, here they are:

Is the event triggered by the CP:

if(craft()->request->isCpRequest()){}

Check the logged in user's permissions:

$userPermissions = craft()->userPermissions->getPermissionsByUserId($user->id);

or use a permission directly:

if($user->can('permissionName')){}

Add an extra param to the criteria that filters to correct region:

$query = $event->params['query'];
$params = array( ':regio' => '["us","eu"]' );
$query->andWhere('content.field_regio LIKE :regio', $params);

Send the changed ElementCriterioModel (or query) to wherever it needs to go:

After setting that query, the function just executes and filters the list.

If you use something like this, make sure you filter out the correct section to check on (because the onBuildElementsQuery is fired on almost everything in the CP). But that's where I stopped my search as eventually, we will not be needing it in this project.


Unable to locate message source for category ''

In Craft 2, the Craft default Yii translation method was overridden to only require one value, the value of the translatable string:

Craft::t('My Translatable String');

In Craft 3, Craft reverts to using the default Yii behavior for the Translate method t() and there are two arguments needed.  The first argument is now the category and the second is the translatable string:

Craft::t('pluginhandle', 'My Translatable String');

Adding the category back allows translations from different contexts to avoid conflicts with each other.

Craft uses the app category.  Yii uses the yii category.  And plugins should use their own plugin handles.

The front-end of a site should use site category, and the actual translation files should be saved in translations/locale/category.php (whether that's in craft/ or craft/plugins/mypluginname/)

(Hat tip to Brandon Kelly for helping me understand this better on Craft Slack)


I finally figured this out. I was actually close.

Here's the HTML that I use

        <form>

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

            {{ forms.lightswitchField({
                 class: 'docraptorize-prod-lightswitch',
                 name: 'prod-pdf',
                 on: true
            }) }}

            <input type="submit" class="btn submit" value="{{ "Go!"|t }}">
        </form>

and this is the corresponding JS

var $btn = $('#generate-pdf-hud'),
$form = $('#generate-pdf-form');

$btn.on('click',function(){
    var hud = new Garnish.HUD($btn, $form, {
        orientations: ['top', 'bottom', 'right', 'left']
    });
   return false;
});


Visiting any locale gives the same locale output

The craft path should be 1 level deeper like that '../../craft' instead of '../craft'. This is what was causing it, but I had to reconfigure the locales from fr_fr to fr. It didn't work in original way.


Composer 2 support has been drafted over at craftcms/plugin-installer#4. We’ll merge that in once Composer 2 is officially released.

~~In the meantime, if you really need to get Craft working with Composer 2, follow the instructions at craftcms/plugin-installer#3.~~

UPDATE: craftcms/plugin-installer and yiisoft/yii2-composer have both been updated to support Composer 2.


The goal for enabling dev mode so I can troubleshoot things while not showing those ugly errors to anyone else.

If that's all you're looking for, there is a per-user account setting for this under the user account's preferences:


How do I get past this MySQL error installing Craft 3 using CLI

This is all very specific to the box you're using, and how it's configured. I realize Scotch Box is a historically popular setup; you might also consider Homestead as it is geared specifically for PHP development.

Anyway, according to the Scotch Box docs the setup should be:

Database Host: localhost
Database User: root
Database Password: root

Which I assume you're doing in the second example? You are also running all of this from inside of the box, yes?


There is! It's called cpEditUrl.

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

Or shorter (thanks to MISC):

{% if currentUser.admin %}
    Edit entry
{% endif %}

Or forget user group altogether (thanks to Phil Gyford and bennobo):

{% if entry.isEditable() %}
    Edit entry
{% endif %}


Bulk selecting Members and then including them in an email to another specific Member in a different member group

This is definitely possible. While certain features can be done with a custom module, my answer will focus on using Sprout Email as that plugin makes it easier to give your users more control in the email management workflow.

Sprout Email comes with several Notification Events. For example, when your customer submits their inquiry form you could configure a Notification Email to watch the 'When an Entry is saved' event and trigger an email to your customer or an admin or both. You can configure more than one email to the same event. In this example I'm assuming your form is a front-end Entry Element. However, if you're using Sprout Forms, Sprout Forms comes with a 'When a form entry is saved' event and Sprout Email has a Custom Notification Event API so it's possible to add support for other scenarios as well.

By default, the Notification Events are fairly simple. But if you need to be more specific than 'When an entry is saved' from a particular section you could further limit the scope of when the event is triggered using the Send Rule setting to, say, check if the author of the entry is in one of the particular groups you want to send to.

While there are simple default templates to get you up and running quickly, the Notification Emails sent are completely customizable via Email Templates and you can include personalized data in your email from the data available to the event you are triggering.

This means you can include whatever link you need in your email and whatever info you want to share that was submitted from the form such as the person's name in a 'Dear So and So' part of the message or all of the submitted responses so they can have them on record as well.

The link you include in the email could be constructed dynamically and include an ID or some other reference in it so that when the user clicks, you can look for that ID, validate the user, and pull in the submitted information or other info onto the results page. All of that will happen outside of Sprout Email and directly in Craft just as any other page. The only thing provided by the email integration for these features is the ability to construct the link in the email with the appropriate info so that you have what you need to do what you want to do.

In the case where the customer clicks "Hire" there may be a couple of events to consider. For one example, let's say when the customer hit's hire you trigger a re-save Entry event where you update the submitted Form and mark a lightswitch field to true. Again, you've triggered a Save Entry event and you can use the 'When an Entry is saved' Notification Event to trigger an email. In this case, you may want to limit the Notification to be triggered only when the Send Rule validates and finds that your 'hired' lightswitch setting is set to true.

To mention one other feature, you can also enable Sent Email tracking in Sprout Email. If you do, Sprout will record each email that was sent and capture who it was sent to, the HTML of the email that was sent, and some other metadata. If a user ever reports they did not receive a message you can check the Sent Email history and you have the option to review or resend Sent Emails.


Sessions are initialized by Craft, and plugins are loaded/called after that, so you'll have to assume the session is already up.

Not sure about your use case, but here is how you could execute code once per session:

if(!craft()->httpSession->get('initialized'))
{
    /*
    Your code executed once per session goes here
    */

    craft()->httpSession->add('initialized', true);
}


How do I define an entry's META description?

The Title field will be a part of every entry 90% of the time ('Singles' don't need a Title).

To add a custom field in Craft:
Settings > Fields > (create a field)

To add the new field to a content type:
Settings > Sections > (click the "Edit content-type" link to the right) > (drag your new field into the blue box) > hit Save.

I like to create a separate custom field for each e.g. "Meta Title" and "Meta Description" - I then add these to a separate tab within a given content-type. (see attached)

Normally, I leave the SEO fields optional.

Then, in _layout.html:

<title>{% block entryMetaTitle %}{% endblock %}{{ siteName }}</title>
<meta name="description" content="{% block entryMetaDescription %}{% endblock %}">

The block tags inherit content from an individual template e.g. domain.com/news/news-article-slug, will make use of a single-entry template e.g. craft/templates/news/_entry.html which will contain:

{% extends "_layouts/_layout" %}

{% block entryMetaTitle %}{% if entry.metaTitle %}{{ entry.metaTitle}} | {% elseif entry.title %}{{ entry.title}} | {% endif %} News | {% endblock %}
{% block entryMetaDescription %}{% if entry.metaDescription %}{{ entry.metaDescription}}{% else %}{{entry.summaryText}}{% endif %}{% endblock %}

{% block content %}
...
{% endblock %}

The above will display any content which the client decides to add to the custom fields, OR if nothing has been added the template will display the entry Title + Summary Text (in this case)

This post might also help you to define your own approach: How do you handle SEO on your site?


How Can I load Inline CSS in the Redactor Editor?

You should first go to the Settings > Fields
Then click on the particular field in which you have selected the Redactor as a field type.
Then you can see Advanced option at the end of the page and Uncheck "Remove inline styles" options there.

So Redactor Editor will not remove inline CSS from your added html content.


Match Matrix Fields Before Looping Through Results

Updated Answer

Turns out the original answer only works if you've got an single instance of a Matrix Block on the entry.  If you have multiple, it will search through all of them and return results for any block that has any of the relations you're looking for, in spite of the inclusion of and.

As of the next post-3.0.9 release, you'll be able to get relational matches from individual Matrix Block instances using a method like so:

{% set targetModel = craft.categories.id(5).one() %}
{% set targetPart = craft.categories.id(20).one() %}

{# be sure and set the field ID of the Matrix field you're interested in here %}
{% set entryIds = craft.matrixBlocks.fieldId(55).relatedTo(['and',
        { targetElement: targetModel, field: 'model' },
        { targetElement: targetPart, field: 'part' },
    ])
    .select(['ownerId'])
    .distinct()
    .column()
%}

{% set entries = craft.entries.id(entryIds).all() %}

{# display the results #}
Total: {{ entries|length }}

    {% for entry in entries %}

{{ entry.title }}

    {% endfor %}

Original Answer
Assuming the setup in your question, something like this should work:

{# These are just two examples, but get the relevant target model and part categories however you want #}

{# resolve to the "Cessna" category #}
{% set targetModel = craft.categories.id(4).one() %}

{# resolve to the "Propx45" category #}
{% set targetPart = craft.categories.id(6).one() %}

{% set entries = craft.entries.section('flightCompany').relatedTo(['and',
    { targetElement: targetModel, field: 'planeDetails.model' },
    { targetElement: targetPart, field: 'planeDetails.part' },
]).all() %}

{# display the results #}
Total: {{ entries|length }}

    {% for entry in entries %}

{{ entry.title }}

    {% endfor %}

Here's the relevant "relations" part of the docs: https://docs.craftcms.com/v3/relations.html


svgicons fieldtype - how to output in template?

Never used the plugin before, but from glancing at their docs, it looks like entry.icons.icon is what you're looking for.

Any other properties on their SvgIconsModel should work as well.


Your condition {% if entry.contentMatrix.first %} will check if there exists a block in your field or not, it does not check if your current block is the first or not. Since there is one the condition will always become true. What you want to do is to check if you are in the first loop or not so I would suggest you to do something like this

{% for key, block in entry.contentMatrix %}
    {% if key == 0 %}

Or something like that


getNextSibling for next product in product type

getNextSibling works in the context of a Structured Section for Entries and for Categories because both of them have the concept of a hierarchy.  i.e. in a Structured Section and a Category Group, each element can have parents and children.

Commerce Products don't have hierarchy natively.  Could be a bit of a pain to maintain, but you could simulate it by adding an "Order" number field to your product field layout and manually enter the order for each product in a product type, grabbing all of them in Twig and doing the sorting there.


Based on our comment thread, I would suggest to perform a manual update of Craft.

Download and unzip the latest copy of Craft, and replace the old app folder with the app folder that you just unzipped. No other files or folders need to be replaced.

Make sure to change the permissions of your new app folder, so you can perform auto-updates in the future.


Updated the PHP on server. Getting this error: Please ensure that $craftPath is set correctly

All Craft is doing is using PHP's is_file() method to check if the supplied path to craft/app/index.php returns true or not.

Take Craft out of the picture and setup a simple PHP script that does

<?php

if (is_file('path/to/craft/app/index.php')) {
    echo "found it";
} else {
    echo "oops";
}

If you get an "oops", then there is some environmental issue (PHP permissions, open_basedir restrictions, Suhosin, mod_security, etc.) that is preventing PHP from finding that file that will need to be addressed.

If it is permissions related (the most common cause), there is a handy script here that will properly set the permissions for a Craft install: https://github.com/nystudio107/craft-scripts/tree/master/scripts


End user sign in and/or registration template example

Here is an example of how to do a login form for users with existing accounts: http://buildwithcraft.com/docs/templating/login-form

You can see more form examples in the left hand menu of that page.


Access env variables in custom php files

If that is really all that you're doing, and you have no other integration with Craft, you can parse the .env however you like. Craft uses vlucas/phpdotenv internally so that library is already in your vendor directory. You should be able to pick that up after including Composer's autoloader.
If however you have any kind if integration with Craft, look at web/index.php and see what's going on in terms of bootstrapping there, copying the parts necessary for your application.


Search result based on a specific field in a related entry in a matrix

Yes, you're right to better not use the search parameter for such things.

Instead get all the product variants that match your criteria first (e.g. size, color) and then query for all related products. Be careful with the field parameter, as your relation is between a Matrix field and your product variant entries.

Code is not tested (as you might guess, hehe):

{% set category = craft.categories.slug('skisko').first() %}

{% set sizeParam = craft.request.getParam('size') %}
{% set colorParam = craft.request.getParam('color') %}

{#
 # Get product variants matching our search
 #}

{% set variantParams = {
    section: 'productVariants',
    variantStock: '> 0',
    variantSize: sizeParam,
    variantColor: colorParam,
} %}

{% set variants = craft.entries(variantParams) %}

{#
 # Get the products related to these variants
 #}

{% set productParams = {
    section: 'products',
    relatedTo: [
        'and',
        {
            targetElement: variants,
            field: 'colorVariants.myRelationField',
        },
        {
            targetElement: category,
            field: 'myCategoryRelationField',
        }
    ]
} %}

{% set products = craft.entries(productParams) %}


You need to rename that snipcart-craft-webhooks-plugins folder to snipcartwebhooks in order for Craft to recognize it.


How do you create a front-end form for users to submit content?

If the users are authenticated and have permission to post to the event section, you would use an entry form to accept posts from the front end.

Example from the above linked page...

<form method="post" action="" accept-charset="UTF-8">
    <input type="hidden" name="action" value="entries/saveEntry">
    <input type="hidden" name="redirect" value="viewentry/{id}">
    <input type="hidden" name="sectionId" value="10">

    Title
    <input id="title" type="text" name="title">

    Body
    <textarea id="body" name="fields[body]"></textarea>

    <input type="submit" value="Submit">
</form>

Deliberately removed from the example above is this <input type="hidden" name="enabled" value="0">, since it'd be redundant and make it more obvious how one might tamper with the form. Setting enabled to 1 would allow submitted posts to go live immediately.

If you'd like to accept guest entries you can use Pixel and Tonic's GuestEntries plugin. Keep in mind that the submissions will still be assigned to the Craft author (user with appropriate permissions) that you designate. The front-end form would look nearly identical, with a hidden action of guestEntries/saveEntry...

<form method="post" action="" accept-charset="UTF-8">
    <input type="hidden" name="action" value="guestEntries/saveEntry">
    <input type="hidden" name="redirect" value="viewentry/{id}">
    <input type="hidden" name="sectionId" value="10">

    Title
    <input id="title" type="text" name="title">

    Body
    <textarea id="body" name="fields[body]"></textarea>

    <input type="submit" value="Submit">
</form>

The plugin's settings let you define default authors and entry statuses for each channel:

GuestEntries also adds a guestEntries.beforeSave event that you can hook into with your own plugin and further act on submissions before they're added to the database.


User data segregation for multi-sites in Craft 3?

Craft 3 multi-site is an extension of locales in Craft 2, so how the data is stored is virtually identical.

The difference is that locales in Craft 2 are tied to language/country codes, but sites in Craft 3 are more abstract concepts that are user defined.

  If I have 'Site A' and 'Site B' running off the one install and someone creates an account on Site A, will they also have an account on Site B?

User accounts are global.  They are not created on a per-site basis, but they can be restricted on a per-site basis through user/user group permissions.

  Will we be able to restrict which CP users see data from which site?

User/user group have site permissions for elements that support it just like they have "locale" permissions in Craft 2.


Does normal authentication occur before userSession.onBeforeLogin event?

The onBeforeLogin event is fired after the username/password is already authenticated, but before the actual authenticated session is started, which is why you're seeing the behavior you're seeing.

For the same reason that you wouldn't expect the onBeforeSaveEntry event to be fired before entry validation has occurred.

I believe to pull off what you're looking for, we'd need to add a new event... something like onBeforeAuthenticateUser.

Probably worth adding as a feature request.


When you are following the each-locale-gets-its-own-index.php-file pattern as outlined in the official KB article, “How do I show localized content on the front end?”, then you do not need to include the locale ID in your sections’ Entry URL Format settings.

For example if you have a News section, and you want Arabic entries to get URLs that look like:

http://www.site.com/ar/news/my-entry-slug

Then the Arabic Entry URL Format should just be this:

news/{slug}

not this:

ar/news/{slug}

Everything leading up to “news/{slug}”, including “ar/”, is handled by your Arabic site URL, as defined in your config/general.php file’s siteUrl setting:

'siteUrl' => array(
    'en' => 'http://www.site.com/',
    'ar' => 'http://www.site.com/ar/',
    // ...
),


How can I count current indexing inside a loop?

Twig offers special loop variables that makes it easy to know indexing of a loop.
You can use loop.index to count your current indexing of the loop, which will starting at 1.
If You want to start your indexing from 0 so simply add 0 after loop.index like loop.index0.
There are other loop variable as well.
Like:

loop.revindex
loop.revindex0
loop.first
loop.last
loop.length


You need to update the locale to en_ca in the control panel under Settings->Locales.


Searching for entries across multiple fields including a relationship

I think I just had my Craft "Lightbulb moment".

I've got this working now. Once I realised that I needed to retrieve the category as an object in order to match against it using relatedTo it made more sense.

I also realised that I needed to used a wildcard rather than an empty string if a parameter was missing.

Here's my solution:

{% set cat = craft.request.getParam('category') ? craft.request.getParam('category') : '' %}
{% set start_date = craft.request.getParam('start_date') ? craft.request.getParam('start_date') : 0 %}
{% set wage_from = craft.request.getParam('wage_from') ? craft.request.getParam('wage_from') : 0 %}
{% set wage_to = craft.request.getParam('wage_to') ? craft.request.getParam('wage_to') : 9999 %}
{% set location = craft.request.getParam('location') ? craft.request.getParam('location') : '*' %}

{%
  set category = craft.entries({
        section: 'apprenticeshipsCats',
        title: cat
  })
%}

{%
  set results = craft.entries({
      section: 'vacancies',
      relatedTo: category,
      location: [
            'and',
            '= ' ~ location
        ],
        wage: [
          'and',
          '>= ' ~ wage_from,
          '<= ' ~ wage_to,
        ],
        startDate: [
          'and',
          '>= ' ~ start_date
        ]
    })

%}

So I still fetch the parameters and set default values for them, note the wildcard if "Location" is empty.

But then I get the category to be searched as a craft entries object.
Once I have that I can use its reference in my results query and bingo!


Loop through JSON object in Twig from the database

You'll simply need to decode the JSON string. Unfortunately, Twig doesn't ship with a json_decode filter, but there's a plugin.

Here's how you'd use it:

{% for block in entry.gridcontrol|json_decode %}
  {% set entry = craft.entries.id(block.id) %}

    {{ entry.title }}

{% endfor %}


Sprout Forms or Craft not sending email to Craft user email addresses

As mentioned in the comments, this is likely an email configuration issue and Brad's comment should be taken to heart:

  both sendmail and PHP's mail are notoriously unreliable and shouldn't be used in production environments

Craft should not be treating user emails differently than non-user emails and Sprout Forms isn't doing anything unique when it sends notification emails, it's just piggybacking on what Craft is doing.

Sending your email through a service like Mailgun (or any similar service) will give you more visibility into what's happening and what you may need to troubleshoot. Sprout Email has a Sent Email Element Type that you can enable to help troubleshoot some email deliverability issues on the Craft side of things.

For two good overviews on troubleshooting email errors in Craft, see:

https://craftcms.com/support/troubleshooting-email-errors - Craft Docs
Troubleshooting and debugging errors in PHP - Straight Up Craft

Another direction to consider when troubleshooting an error like this may be to look closer at the From headers and what emails you are sending to. Is it really just Craft Emails vs non-Craft Emails or could there be other patterns? For example, maybe the emails that aren't being received are all gmail addresses. In some cases, if you are sending to a gmail address you own from a gmail address you own, Google may suppress the email from appearing in your inbox.


the general.php file was setup for a multi environment but was missing

'*' => array(
),

as per the notice here:
https://craftcms.com/docs/multi-environment-configs

{basePath}assets/images/ was the correct file system path once the array had been added.


PHP Core Warning – yii\base\ErrorException Module 'newrelic' already loaded craft 3

Not really related to Craft or the update from Craft 2 to 3.  You'll probably want to contact your hosting provider.  It sounds like there are multiple attempts at loading the newrelic module in your php.ini file.


You can set postLogoutRedirect in your config/general.php (docs) to redirect your users to a specific page, something like 'postLogoutRedirect' => 'your-page'
If you want to use an existing page, say your homepage, and display an alert you could set 'postLogoutRedirect' => '/?loggedout' and check for it in your template using:
{% if craft.app.request.getParam('loggedout') is not null %}

You have been logged out

{% endif %}


Comparing matrix blocks by type and field value

My guess would be that this is happening due to lingering parameter values, as it looks like you’re not using clone() at all.
For every place that you are calling entry.programme, change to clone(entry.programme). For example:
{% set talks   = clone(entry.programme).type('item').all() %}
{% set odTalks = clone(entry.programme).type('item').od(':notempty:').all() %}

If you don’t clone the entry query before setting parameters on it and executing it, then whatever parms you set will stay set on it the next time you access the same entry query further on in your template.
(That is mentioned throughout the docs wherever we demonstrate setting parameters on element query field values, e.g. under Working with Matrix Field Data. But I realize it’s awkward & annoying – see craftcms/cms#5640 for my idea of how to improve this in Craft 4.)
If adding clone() functions everywhere doesn’t solve this on its own, the next thing I’d do is run the query through getRawSql() and see what that produces:
<pre>{{ clone(entry.programme).type('item').od(':notempty:').getRawSql() }}</pre>

You can paste the query that’s output into a MySQL client, and see if there’s anything obviously wrong with it. Or paste it into your question above.


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

So just add 2 spaces at end of line!


That error is not really related to Craft, but to your test server's environment.

Your php.ini file is trying to load an opcache.so module, but it can't find that module on the server's file system.

Once you correct that, this particular error will go away.


Set a dynamic `activateAccountSuccessPath`

Completely untested, but something like this should do it.  Create a simple plugin and add this to the main plugin class:

public function init()
{
    craft()->on('users.onBeforeActivateUser', function(Event $event)
    {
        $user = $event->params['user'];

        craft()->config->set('activateAccountSuccessPath', 'members/'.$user->username);
    });
}


maybe this article will help! https://nystudio107.com/blog/autocomplete-search-with-the-element-api-vuejs


How to fetch entries in custom plugin Craft 3?

For instance like this:

$entries = Entry::find()
    ->section('sectionName')
    ->orderBy('fieldName')
    ->limit(null)
    ->all();

Have a look here in the documentation (for the code examples you can toggle Twig and PHP view for code examples):
https://docs.craftcms.com/v3/dev/element-queries/entry-queries.html

Note that if you add use craft\elements\Entry; to the top of your plugin file, you can use the Entry::find() directly, you don't need the namespace prefix like in the examples in the documentation (for instance \craft\elements\Entry::find();).


How can I create list of a group’s fields for a select field’s options in my Field Settings?

Your plugin will need a few things.

A FieldType
FieldType Settings using defineSettings() and getSettingsHtml() method
A template that will render your settings which will be referenced in the craft()->templates->render function of the getSettingsHtml() method

On the settings template, I believe you will need two dropdowns.  The first, will just be a dropdown of available Sections.  Upon selecting the section, you would update the second Dropdown to have a list of the Matrix fields within that section, or a message saying that no Matrix fields we're available.  Or perhaps, you can just sort out which Sections have Matrix fields to start off with, and only display those Sections in the dropdown.

I'm not sure if there is a more efficient way to just grab Matrix fields, but here are some functions that may help you get to what you need:

Get all available Sections

$sections = craft()->sections->getAllSections()

Get a specific section by ID

$section = craft()->sections->getSectionById(1);

Get the FieldLayoutFieldModels attached to a Section (Note Fields are not related to the Section directly, they are related to a FieldLayout, which is related to an EntryType, which is related to your Section).  In the example below, I have assumed you are grabbing the first EntryType using getEntryTypes()[0] however in your code, you'll likely have to do a bit more logic to make sure you're getting what you want:

$fields = $section->getEntryTypes()[0]->getFieldLayout()->getFields();

Once you have the FieldLayoutFieldModels, you can access each FieldModel using the getField() method and check which type of field type it is:

foreach ($fields as $field)
{
  $field = $field->getField();

  if ($field->type == 'Matrix')
  {
    // Build an array of the options for your Matrix fields dropdown
  }
}

Once you build an array of your options, you can hand them off to your fields settings template in the getSettingsHtml() method and loop through and output them in your template file.  The doc pages referenced at the beginning of this post go over that in more detail.

return craft()->templates->render('yourplugin/_fields/settings', array(
    'settings' => $this->getSettings(),
    'matrixFieldOptions' => $matrixFieldOptions
));


TypeError: Argument 1 passed to craft\services\Fields::getGroupById() must be of the type integer, null given

This could be due to an issue with your project-config being out of sync somehow. You could try the new ./craft project-config/rebuild console command that's just been added to Craft and see if that gets you back on track.


How can I output child urls that reflect a structured menu hierarchy when the structure has no URL format specified?

Craft can't really produce the uri patterns/routes you need automatically without giving it something to work with. With that said there are a couple of ways to approach this.

1) One option is to simply make your pages section into a structure; creating the needed hierarchy elements, and use it directly to generate your navigation. You may also want to specify additional 'entryType(s)' for header items, etc (i.e. items that don't have a corresponding page and/or are used exclusively for creating the nested route structure or for navigation headers, buttons, etc). You can then test entry.type in your template and deny or reroute the request accordingly.

2) Another option is to define a url format for your nav structure, which represents the uri pattern(s) that you would like to have (i.e. if the structure represents the site root then set the uri to {slug} and children to {parent.uri}/{slug}).

Using this approach, you would want to set up a template for your navigation structure which essentially includes the corresponding page template, as needed.

Something like this perhaps:

{% if entry is defined %}
    {% set relatedPage = entry.contentLink.first %}
    {% type = relatedPage.type %}
    {% include ["pages/_types/" ~ type, "pages/_types/default"] with { 'entry': relatedPage } %}
{% else %}
    {% redirect '404' %}
{% endif %}

Notice that when including the page template, we are redefining the entry variable to be the related page, so that the 'page' template doesn't have to worry about it, and can be loaded directly or via the navigation template as needed.

Note: you may want to disable urls for your pages channel if you don't ever want users to access pages through those routes.


You can use
{{ subscription.subscriptionData.plan.amount }}

to get the price of the plan the customer subscribed to.
That returns in cents so you'll need to convert and format it.
{{ (subscription.subscriptionData.plan.amount / 100) | currency('USD', stripZeros=true) }}


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


How to optimize nested reverse relations?

There’s a lot going on here. Let’s first work out the outline of your algorithm, and therefore where things could be improved.

Query and iterate memberships

Query and iterate members

Query first asset

Get asset transform

Note: Every time a transform is used, Craft first has to check whether the transform has been generated (from the docs)

As you can see, there are multiple levels of nested relations going on. You’ve mentioned using eager-loading already, but it is definitely beneficial here. One of the cool things Craft can do is eager-load nested relations.

Have you tried something like this?

{% set memberships = craft.entries({
    section: 'membership',
    order: 'cf_membershipShorthand',
    with: [
        '{relatedMembersField}.cf_ma_asset'
    ]
}) %}

{% for membership in memberships %}
    {% for member in membership.{relatedMembersField} %}
        {% set image = member.cf_ma_asset[0] ?? null %}
        {% set imageParams = { width: 30, height: 30 } %}

        {% if image %}
            {# Output image with transform #}
        {% endif %}
    {% endfor %}
{% endfor %}

Where {relatedMembersField} is the handle of your entries field.


The problem was resolved by changing the headers set:

let form = new FormData(this.form);
let request = new Request('/', {
  credentials: 'include',
  method: 'post',
  mode: 'same-origin',
  redirect: 'follow',
  headers: new Headers({
    'Accept': '*/*',
    'X-Requested-With': 'XMLHttpRequest'
  }),
  body: form
});

Instead of declaring the Content-Type in the request, I set the encoding type on the form itself, this step is optional as the request sets as multipart/form data by default I think.

<form method="post" enctype="multipart/form-data">
..
</form>


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

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

Then simplified my template like this:

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


Passing Twig Variable into Template from Include?

I suggest using macro (and switch tag instead of if).

{% macro ratio(block) %}
{% spaceless %}
    {% switch block.imageRatio %}
        {% case "thumb" %}
            imageVariantsThumb
        {% case "16by9" %}
            imageVariants16by9
        {% case "3by2" %}
            imageVariants3by2
    {% endswitch %}
{% endspaceless %}
{% endmacro %}

Macro would be used like this:

{% import 'macro' as macroRatio %}
{% set imageRatio = macroRatio.ratio(block)|trim %}


Visitor drop off since moving over to Craft CMS

I wouldn't be overly concerned about bounce rates and such, I'd be more concerned about conversion metrics. The reason is that many things affect bounce rate; if the new site is better designed, people may not need to click on additional pages to find out what they want to know, for instance.

There's nothing inherent with Craft that would result in this type of a falloff. For sure making sure all of the 404 errors get buttoned up would be a good start, and the Retour plugin can assist with that. You could also consider installing the SEOmatic plugin to assist you with modern SEO.

Disclaimer: I'm the author of both of those plugins.


How to hide createAccount select by default • Charge 2 Plugin

Eventually I just edited customerDetails.html and swapped out the select with a hidden field. Done.

{{ forms.hidden({
    name: 'createAccount',
    id: 'createAccount',
    value: 'yes'
}) }}


I'm not entirely sure why you need to resave all the entries but I do know how you can do it quickly and easily. I'd recommend using the Walk plugin by Michael Rog to do this.

The plugin is pretty well-documented in the repository README, but I'll outline the steps here for you as well:

Download the plugin folder, drop it in /craft/plugins, and install the plugin in the Craft CP.
Add the yiic file from the repository into the base folder of your Craft install (next to the craft folder).
Open your terminal, cd to your Craft install, and run the following:

php yiic walk entries --section=blog --limit=null entries.save

Obviously replace blog with the name of your section.

Hopefully that does the trick for you! Let me know if you have any questions...


How to reorder structure entries in the Admin panel?

I don't know if there's a quick/easy way to do this within the admin area, but if you go to Entries, then click on your Structure, there's a little 4-dot symbol to the left of the Entry's title (make sure you have Structure selected in the drop-down to the right of the Search bar). You can click that 4-dot icon and move them around manually. Doing this will reorder the way entries appear on your site.

If you're just looking to reorder the entries within the admin area (and not reorder them on the front-end site), then click the drop-down to the right of the Search bar. You'll see options like Title and Post Date. Once you click one of those, you'll see headers for Title, Post Date, etc., that you can click on to sort entries. Again, this method won't affect how entries are displayed on your site; this only affects the admin area.


How to query in MySQL all entries with related categories

The relations table holds all of the information about relations between Craft elements (entries and categories in your case).

So you would use the sourceId and targetId columns of the relations table and join on the id columns of the entries and categories tables in your example.


Impossible to invoke a method on array. How to merge multiple objects and keep as objects

You can achieve this with Craft's shuffle() method and Twig's slice filter (like you mentioned in your answer).

{% set newsletterImages = newsletter.imagesCongratulations.all() %}
{% set newsletterImages = newsletterImages | merge(newsletter.imagesCis.all()) %}
{% set newsletterImages = newsletterImages | merge(newsletter.imagesSection3.all()) %}

{% set shuffledImages = shuffle(newsletterImages) %}  // Shuffle our "master" array

{% for image in shuffledImages[:6] %}  // Get the first 6 images
  {{ image.title }}<br>
{% endfor %}


Sort matrix blocks by date and limit to 10 entries

Your entry.agendav2 is not an array of elements but a ElementCriteriaModel so you can include both properties in your query

{% for block in entry.agendav2.limit(10).order('Datum') %}

That's basically it.

Edit: you can search for entries in the future with

 Datum('>= ' ~ 'now'|date('c'))

Like stated here https://craftcms.stackexchange.com/a/23697/5557

Edit:

After we discussed the issue in my comments I came up with this solution

{% set matrixBlocks = craft.yourPluginHandle.getSortedMatrixBlocks() %}
{% for matrix in matrixBlocks %}
    ...
    {{ matrix.datum }}
    ...
{% endfor %}

And insert this in your PluginVariable

public function getSortedMatrixBlocks(){
    // the id of your matrix field
    $matrixFieldId = 61;

    // check your database for your matrix field table and insert your Datum field column
    // it will be a string like field_{blockHandle}_{fieldHandle}
    // for me it is
    $matrixFieldDatum = 'field_test_datum';

    // lowercase handle of your field
    $matrixFieldHandle = 'matrixfield';
    $matrixIds = craft()->db->createCommand()
        ->select('craft_matrixblocks.id')
        ->from('matrixblocks')
        ->where('craft_matrixblocks.fieldId = :fieldId', ['fieldId' => $matrixFieldId])
        ->limit(10)
        ->join('matrixcontent_'.$matrixFieldHandle, 'craft_matrixblocks.id = craft_matrixcontent_' . $matrixFieldHandle . '.elementId')
        ->order($matrixFieldDatum . ' ASC')
        ->queryColumn();

    $allMatrixBlocks = [];
    foreach ($matrixIds as $id){
        $allMatrixBlocks[] = craft()->matrix->getBlockById($id);
    }

    return $allMatrixBlocks;
}


You're always getting the same set because the entries are first fetched, then shuffled. To achieve what you want, you could do:

{# get all your entries ids #}
{% set allIds = craft.entries().section('yourSection').ids() %}
{# Shuffle all and slice to just 15 #}
{% set shuffledIds = shuffle(allIds) | slice(0,15) %}
{# Fetch your random entries #}
{% set entries = craft.entries.id(shuffledIds).all() %}

Or

{# get all your entries ids #}
{% set allIds = craft.entries().section('yourSection').ids() %}
{# Fetch your random entries #}
{% set entries = craft.entries().id(shuffle(allIds) | slice(0,15)).all() %}

In response to your comment then you could do something like the below:

{# set a random offset #}
{% set offset = random(0, 6000)%}

{# set a random sort #}
{% set orderBy = random(['postDate', 'id', 'title']) %}

{# set a random direction #}
{% set direction = random(['ASC', 'DESC']) %}

{# get 500 ids #}
{% set allIds = craft
            .entries()
            .section('posts')
            .offset(offset)
            .orderBy(orderBy ~ ' ' ~ direction)
            .limit(500)
            .ids() %}

{# Fetch your random entries #}
{% set entries = craft.entries().id(shuffle(allIds) | slice(0,15)).all() %}

With this, you only fetch 500 entries with a random offset and sorting, shuffle that pool and pick 15. This might not be as random but I doubt you'd notice it.


Is there a limit to outputting entries in 'free' version of Craft CMS?

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

To grab all entries, use:

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

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


How to check for a value OR NULL on custom enddate field using yii syntax when calling entries?

Shooting in the dark here, but looking off this ticket and the ECM parameter value syntax in the docs, could you do something like:

{% paginate craft.entries({
    section : 'dealDirectory',
    limit   : pageSize,
    startDate : '<=' ~ now
    endDate: 'or', '>= ' ~ now, 'not null'
}) as pageInfo, dealEntries %}

The or is a total guess based on the and in the other ticket.


Get entries by custom matrix / date time field

I found the solution by using the following:

{% set startDate = now %}
{% set endDate = (now | date_modify("+2 months")) %}
{% set allTraining = craft.lowblocks.blocks.fieldId(72).type("trainingDateTimeDateTime").order("dateTimeFrom").limit(null) %}
{% set entryIds = [] %}
{% for course in allTraining %}
    {% if (course.dateTimeFrom >= startDate) and (course.dateTimeFrom <= endDate) %}
        {% set entry = course.owner %}
        {% set entryIds = entryIds | merge([entry.id]) %}
    {% endif %}
{% endfor %}
{% set entries = craft.entries.section("training").id(entryIds).fixedOrder(true).status("live,pending") %}


Repopulate dateTime field in plugin settings page

Long story short, this is a bug in Craft 2.x that's already been fixed in the Craft 3.x branch.

Considering there is a workaround for 2.x and the proper fix would be pretty ugly in 2, we're just going to let this one die a slow death with the release of Craft 3.


Check your craft/storage/runtime/logs folder for the underlying error message, but most likely you're using GD instead of Imagick, which is required for SVG thumbnails/transforms to work properly.


It would be helpful if you post your code instead of a link, as the metadata available on the linked page may change.

A few considerations:

Make sure your page is outputting metadata for each of the services you mention. It looks like you are outputting some basic and Open Graph metadata, but you don't appear to have any Twitter Card metadata. I've added a list of common meta tags that should help address most social sharing scenarios below.
Most of the services you have document which tags matter to them and some even have debugger tools that can help you troubleshoot.

Open Graph Protocol
Facebook Debugger
Twitter Card Spec
Twitter Card validator
LinkedIn Sharing uses the same Open Graph tags as Facebook

Make sure you consider caching. Sometimes, when you test your shared content the services you share it on will cache it. If you then update your content you may not see the updated version of your content in a link you have already shared until you break that cache.
Structured Data is also becoming an important type of metadata to add to your pages: https://developers.google.com/search/docs/guides/intro-structured-data
This stuff gets complicated to maintain directly in your templates very quickly. Several Craft plugins are available to help manage that complexity. Sprout SEO and SEOmatic are two SEO plugins that are well supported and try to address the majority of SEO best practices that you need to worry about.

Common Meta Tags for Search and Social Sharing

<!-- Search -->
<title></title>
<meta name="description" content="" />
<meta name="keywords" content="" />
<meta name="robots" content="" />
<link rel='canonical' href='' />

<!-- Open Graph -->
<meta property='og:type' content='' />
<meta property='og:url' content='' />
<meta property='og:site_name' content='' />
<meta property='og:title' content='' />
<meta property='og:description' content='' />
<meta property='og:image' content='' />
<meta property='og:image:width' content='' />
<meta property='og:image:height' content='' />
<meta property='og:image:type' content='' />
<meta property='og:author' content='' />
<meta property='og:publisher' content='' />

<!-- Twitter Card -->
<meta property='twitter:card' content='' />
<meta property='twitter:url' content='' />
<meta property='twitter:site' content='' />
<meta property='twitter:creator' content='' />
<meta property='twitter:title' content='' />
<meta property='twitter:description' content='' />
<meta property='twitter:image' content='' />


Cycle tag - last cycle returns same cycle

As you already found out, the loop.index counter increments for each iteration of the loop, not only if you use or print it within your conditional. The best solution to work against it is to get rid of that conditional.

In this case it is in fact possible to catch only those entries you are after, making the conditional redundent

{% for entry in craft.entries.section('gigs').datum('< ' ~ present) %}

{{ entry.title }

{% endfor %}

if it wasn't, you could have done your own counter that increments within the conditional.

{% set index = 0 %}
{% for entry in craft.entries.section('gigs') %}
    {% if entry.datum < present %}
        {% set index = index + 1 %}

{{ entry.title }

    {% endif %}
{% endfor %}


How to deal with too many folders in asset source?

As you have deduced, Assets have a fair amount of javascript attached to each folder and file to deal with all the dragging and dropping. To save resources, a folder gets initialized only when it becomes visible. So, if you're exposing a thousand of those folders at the same time, the JS engine will take quite a hit and consume huge amounts of resources.

In my experience, a good way of mitigating is dividing the subfolders by years and months. Since an entry might not have a post date yet when it's being edited and the post date might change over the course of an entry's lifetime, the path I've come to rely on is {dateCreated|date('Y')}/{dateCreated|date('m')}/{slug}.

Also note that if this is being used in a Matrix block, you'll have to prefix all those variables with owner.


Where should an encryption key be stored?

I'm hardly a security expert but if someone can get to your filesystem or your db, you'd be screwed either way—so what you're really doing is technically obfuscation and not really encryption. Ideally you'd do the crypto on a different server or have a hardware module that does the encryption and sends the result back but that solution probably won't work here.

Like you mentioned, if you're storing data in the database, don't keep your key in the db. That would be like taping the combination to the outside of a safe. If someone got a dump of the database, they'd be able to use the key to decrypt the data, obviously.

Keep it simple. I'd probably opt for somewhere in the filesystem, like in your plugin's config for example. Leave the key blank until you're ready to use the plugin for production and then have the user fill in the value... maybe with something like WordPress's Secret key generator... that way, nobody has the same key even if someone were to get a copy of your plugin's source code.


have you tried setting a time for the end date? because I think Craft always saves time with your date fields.

{% set vDateend = craft.app.request.getParam('dateend')|date('Y-m-d') ~ ' 23:59:59' %}


Commerce: Is there a way to use a countries dropdown with iso codes (US, CH etc) instead of ids?

This should do it:

{% set countries = craft.commerce.countries %}

{% for country in countries %}

{{ country.iso }}

{% endfor %}


How to use the Element API plugin only when logged in?

If you want to restrict the whole API, you can add some code to the top of your /config/elementapi.php file (right below namespace Craft;) that checks for a logged in user, and ends the request with an appropriate status if the user isn't logged in:

<?php
namespace Craft;

$user = craft()->userSession->getUser();
if (!$user) {
    HeaderHelper::setHeader(array('status' => 404));
    craft()->end();
}

Note that you can replace the 404 with another HTTP status code if you want to; pick whatever feels appropriate to your app.

If you want to restrict specific endpoints, but leave others open, the best approach is probably to wrap the above code in a function, i.e.

<?php
namespace Craft;

function requireLogin() {
    $user = craft()->userSession->getUser();
    if (!$user) {
        HeaderHelper::setHeader(array('status' => 404));
        craft()->end();
    }
}

return [
    ...

Then, it's simply a matter of calling this function from your restricted endpoints' transformer callbacks:

'news.json' => [
    'elementType' => 'Entry',
    'criteria' => ['section' => 'news'],
    'transformer' => function(EntryModel $entry) {

        // This endpoint should be restricted
        requireLogin();

        return [
            'title' => $entry->title,
            ...
        ];

    },
],
...


No super easy way around this one, I don't think. You might consider if using blocks is the most appropriate method in this case, or if a simple conditional in the extended template would do the trick:

_layout.html

<nav>
    {% if category is not defined or category.title != 'Smith'%}
       {# Your navigation code here #}
        ...
    {% endif %}
</nav>

If you want/need to use a block, I think your best option is to put the contents of the extended template's nav block (i.e. the default content for the nav block) in a partial template (e.g. _partials/nav.html), and include it like this in the layout and category templates, respectively:

_layout.html

{% block nav %}
    {% include '_partials/nav' %}
{% endblock %}

category.html

{% block nav %}
    {% if category.title != 'Smith' %}
        {% include '_partial/nav' %}
    {% endif %}
{% endblock %}

Yes, its one more template, but it's the most DRY solution I can think of.


How can I get to a category via the category slug using the ElementAPI

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

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

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

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

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


Your /craft/config/social.php file should probably look like this:

<?php

return [
    'lockDomains' => [
        'awebaddress.net',
    ],
];

If you wanted to add more config settings, that would look like this:

<?php

return [
    'lockDomains' => [
        'awebaddress.net',
    ],
    'allowEmailMatch' => false,
];


On multisite setup, currentUser not true in LivePreview

I have found the solution to my problem.

{% if craft.app.request.isPreview %}
    THIS WILL BE SHOWN IN LIVE PREVIEW,
    even if Your domains are
    www.main-cp-domain.com
    www.second-domain.com
{% else %}
   THIS WILL APPEAR TO ANYONE ON FRONTED
{% endif %}

So it does what I need. However, I don't get why craft.app.request.isLivePreview and currentUser are not working in LivePreview, when editing entries for second-domain.com


Craft Commerce Shipping Total Order Price rule

The current rule for the total in Commerce 1 is in craft/plugins/commerce/models/Commerce_ShippingRuleModel.php starting at line 214:

if ($this->minTotal && $this->minTotal > $order->itemTotal)
{
    return false;
}
if ($this->maxTotal && $this->maxTotal <= $order->itemTotal)
{
    return false;
}

Try changing it to use totalPrice and see if that resolves the issue for you:

if ($this->minTotal && $this->minTotal > $order->totalPrice)
{
    return false;
}
if ($this->maxTotal && $this->maxTotal <= $order->totalPrice)
{
    return false;
}

If we were to go ahead and change it in core, it would be a breaking change for other users. The only way around that is to make a new setting.

If it resolves the issue for you, I will look into making the new setting.


Migrating Craft site to another server --- throws 404 for all pages but homepage

99% chance that it is because the .htaccess file did not come over when you copied the files, as it is a hidden file. Copy that over to your new webroot and those interior pages should properly work.


Does Craft Commerce support multi-currency?

Not at this time (version 1.1), but Pixel & Tonic has indicated in Craft Slack that it is on the roadmap.


Is it possible to search an asset filename stored on a remote Amazon S3 volume?

I figured it out.  I was using folderID instead of volumeID.  It looks like this parameter changed from Craft 2 to Craft 3.


Commerce email receipt not sent after order, but manual Send Email in Order screen works

Simple step missing on the setup of this. I needed to actually assign this email to the status New, to send when a New order is placed, in the Order Statuses section, as per this documentation. So simply a case of RTFM:
https://craftcms.com/docs/commerce/3.x/order-status-emails.html#selecting-an-email


Caching not working on page with asynchronously loaded asset transforms

Seems to be the case that Craft won't attempt to resolve these /cpresources/transforms/ URLs until the asset is actually requested, which can mess with a setup like PictureFill where there is no guarantee that the transformed assets will ever be loaded.

Solution in my case was to to set 'generateTransformsBeforePageLoad' => true, in your Craft config array as mentioned here

After doing this, all transform URLs resolve and the page is properly cached.


Is there a way to delete all entries within a section?

I think you're looking for the Delete Duplication Handling option. From the documentation:

  Delete all existing entries in this section, adding only entries from
  this feed. Be careful. Use case: Events, or when only data from the
  current feed is required.

  "I want only the entries from this feed in this section."


Currently not.  If Craft sees that there isn't anything specified for the htmlBody property of EmailModel will run the body property though Markdown and set that to htmlBody.


What's the simplest way of automatically activating/verifying user accounts?

If you have Craft Pro edition installed, in the control panel you can go to Settings->Users->Settings and uncheck "Verify email addresses?" and check "Allow public registration?".

Use a front-end registration for similar to this and it should do what you're looking for.


Page currently being edited by another user notification?

It would definitely have to be a plugin, but I'm not sure the right events are available for a plugin to pull it off right now.

Seems like there would need to be at least two that need to be created.  Some onDisplayEntry event that gets fired as soon as an entry page is viewed and another onEditEntry event that gets fired over AJAX as soon as any field value changes.


When accessing a Category url is there direct access to the Category's fields?

Yes, the CategoryModel for your category will be available to the template as the variable category.

{{ category.title }}

{{ dump(category) }}


How do I get get clean URLs in twig templates

Documentation for removing index.php

http://buildwithcraft.com/help/remove-index.php

You might have to adjust the .htaccess code depending on your server.


Selling tickets to repeating events with Commerce (and Solspace Calendar?)

I think you will have to get your hands a bit dirty with this one.

The Calendar Events fieldtype will get you part of the way, but you still need some module code to pull this off.

A suggested approach is:

Create a product type with the Events fieldtype
Create some module code that creates/updates a product + variants for each date, where the inventory is set to n.
List the events as you would normally do, and pull in the products and its variants with the reverse relationship.

If the available number of tickets is always the same, you could have one field on the event where you enter the number.

If the amount of tickets vary by day, there is probably multiple approaches. Maybe a Matrix field that assumes position of block with quantity field === date in same position/with a date picker, maybe something else.

You can create a example module over at pluginfactory.io


Cleared the log files found at /storage/logs/web.log.

Tried to view an inner page on the website which threw a Craft "Internal Server Error".

Inside the log, I saw "Twig\Error\SyntaxError: Unknown "dump" function".

Googled that message and found the solution.

For other newcomers, when you set devMode to true, the dump() function is available in your templates. When you set devMode to false, dump() is not available and Craft throws an internal server error.

That is why my inner pages would not load.


Does Craft save dates in the locale format?

Where are you seeing the incorrect date, in the database or when you output it in the templates?

I think Craft is probably working as expected here.

Craft will expect the date submitted to be in the correct format for the locale it was submitted from, so will translate it from that format into UTC to save in the database.

Then, when the date is output in templates, it is transformed again to the correct format for the locale it is being displayed in.

The EN locale presumably assumes US date formatting so 01/02/2018 is correct as 2nd January 2018. For European locales, a date submitted as 01/02/2018 will correctly be recognised as 2nd February 2018.

You need to make sure that the date input in your form is formatted according to the expected way for the locale the form is in.


How do I actually add a Digital Product to an order?

You would start out by listing the digital products in your templates. For example, if you had digital product type with the handle of onlineCourses, you would get the list of products like this:

{% set products = craft.digitalProducts.products({type: 'onlineCourses'}).order('price desc') %}

Looping through those is just like looping through variants (since digital products don't have variants) or entries. One thing to note, is that currently digital products do no have a salePrice, if you've been using that for Commerce products - just price.

You would add digital products to the cart exactly like you would add a Commerce product and, as soon as an order is completed, any digital products that were in the order will have their licenses automatically generated.

Please note, unlike Craft Commerce standard products where the purchasable is the products' variant, in the case of Digital Products, the purchasable is the product itself.

For example:

<input type="hidden" name="purchasableId" value="{{ product.defaultVariant.purchasableId}}"/>

vs

<input type="hidden" name="purchasableId" value="{{ digitalProduct.purchasableId}}"/>


If pageLink is an Entry field and image is an Assets field, then you're probably looking for something like this:


Changing Username On Front End To Another Account Email

Just answering this for anyone else who sees this. The case above was confirmed by Brad Bell and was fixed in Craft 2.6.2984. So, going forward, the scenario described above should return an error to handle.


No. Twig gets compiled into PHP and is run entirely on the server.


Can I disable channels in Redactor "Link to entry" feature?

Here is a super hacky way to do this...but it does do the trick.

Locate the JS file responsible for rendering the Element Selector Modal (craft/app/resources/js/compressed/RichTextInput.js)
Search for: {storageKey:"RichTextFieldType.LinkToEntry". This is where the modal gets called.
Nearby, locate "criteria" and change

{locale:this.elementLocale} to {locale:this.elementLocale, section: ['sectionYouWant','otherSectionYouWant']}
Push this JS file to your server and only the sections you include in the section array above will show entries. The other section titles will show, but no entries will show up to select.

Keep in mind that this adjustment will probably be overriden by any Craft update. I bet building your own redactor plugin would be cleaner.


Is asset() a Twig macro you've defined?

Are you sure you're just not looking for the global url() method instead?


Parent are not set anymore after saveElement()

You need to use newParentId:
$navigationItem = new Entry();
$navigationItem->typeId = 4;
$navigationItem->sectionId = $navigationSection->id;
$navigationItem->title = $entry->title;
$navigationItem->newParentId = $herbsNavigationEntry->id;

$navigationItem->setFieldValue('navLink', '/tags/' . $entry->slug);

if (!Craft::$app->elements->saveElement($navigationItem)) {
    Craft::error('Couldn’t save the entry "' . $entry->title . '"', __METHOD__);
}


How to use the native datepicker ui in custom fieldTypes?

Here’s what your field type’s getInputHtml() method should look like:

public function getInputHtml($name, $value)
{
    // If $value['trial_end'] is set, make sure that it's a DateTime object
    if (!empty($value['trial_end']))
    {
        $value['trial_end'] = DateTime::createFromString($value['trial_end']);
    }
    else
    {
        $value['trial_end'] = '';
    }

    return craft()->templates->render('myplugin/input', array(
        'id'    => craft()->templates->formatInputId($name),
        'name'  => $name,
        'value' => $value,
    ));
}

Then your plugin’s input.html template would be responsible for showing the Datepicker input.

The easiest way to create a Datepicker input is to either include the _includes/forms/date.html template directly into your template, or use the date() macro from _includes/forms.html.

{% from "_includes/forms" import date %}

{{ date({
    id: id ~ '-trial_end',
    name: name ~ '[trial_end]',
    value: value.trial_end
}) }}

However if you need to tweak the HTML, such as adding that ata-stripe="trial_end" attribute, you can just copy the HTML from the _includes/forms/date.html template directly into yours.

In your case, it’s probably not working because you have that hasDatepicker class on your <input>, which tells the Datepicker JS that a datepicker instance has already been assigned to that input, so the new datepicker initialization is getting skipped. Remove that class and you should be good to go.

When an entry is saved, you will need to convert the user-submitted date value into a DateTime object, which you can do using DateTime::createFromString().

On a normal field type you would want to put that code within prepValueFromPost(), like this:

public function prepValueFromPost($value)
{
    // Convert trial_end to a DateTime object
    $value['trial_end'] = DateTime::createFromString($value['trial_end']);

    return $value;
}

However in your case, if your field type isn’t storing any data and its defineAttributeConfig() method is returning false, a better place to put it would be in onAfterElementSave():

public function onAfterElementSave()
{
    // Get the raw POST value for this field
    $value = $this->element->getContent()->getAttribute($this->model->handle);

    // Convert trial_end to a DateTime object
    $value['trial_end'] = DateTime::createFromString($value['trial_end']);

    // ...
}

If you’re looking for an example third party field type that works with dates, check out our Store Hours plugin. It’s using timepickers rather than datepickers, but those both work exactly the same.


The issue appears here

$isConsoleRequest = Craft::$app->getRequest()->getIsConsoleRequest();
if (!$isConsoleRequest && !Craft::$app->getUser()->enableSession) {
    return null;
}

For whatever reasons Craft::$app->getRequest()->getIsConsoleRequest(); does not return true -> !false becomes true -> it tries to grab the user which should be an instance of craft\web\User to have the property enableSession but since it is a console request you receive craft\console\User which has not such a property.

I guess it's a bug or something


There are two classes behind each Twig tag: a Token Parser and a Node.

The Token Parser is responsible for actually parsing the template, once Twig has tokenized it, and returning your Node class to represent it. The Node class is responsible for compiling itself into actual PHP code.

{% requireLogin %} is about as simple as it gets, because it doesn’t have to worry about parsing parameters, expressions, sub-content, etc. You can use its Token Parser and Node classes as a starting point - they’re located in craft/app/etc/templating/twigextensions/.

Once you’ve created those classes, you will need to create a Twig Extension, which will be used to connect your TokenParser to Craft’s instance of Twig. Give it a getTokenParsers() method which returns an instance of your Token Parser class (example).

(Note that if you use the Craft namespace in these clasess, you will need to prefix all of Twig’s class names with \, e.g. \Twig_TokenParser.)

Finally you need to register your Twig Extension from your plugin’s primary class using the addTwigExtension hook:

public function addTwigExtension()
{
    // Import the Twig Extension, Token Parser, and Node classes
    Craft::import('plugins.mypluginfolder.MyTwigExtension');
    Craft::import('plugins.mypluginfolder.MyTokenParser');
    Craft::import('plugins.mypluginfolder.MyNode');

    // Return a new instance of it
    return new MyTwigExtension();
}


Single entry with 450 Matrix blocks throwing error on save

Most likely you're bumping into php.ini limitations.  I'd bump the values of memory_limit, post_max_size and max_input_vars and see if that helps.

They are common culprits when POSTing large amounts of data (which is what 450 Matrix Blocks would be considered).


Locked users' content fully blocked and unable to unlock

You're likely running into a bug that was fixed in 2.3.2636 where a locked user could cause all sorts of havoc on the CP.

If your version/build is before that, update to the latest and you shouldn't see it again.


Formerly - Checking if e-mail already entered

(this is more of a jquery question than Craft, but...:))

The reason this doesn't work is because $.post works asynchronously (that's the A in AJAX). It creates a request, with a success handler (the function), then the submit handler continues execution. The success handler isn't run until the request completes, which is probably a couple of hundreds of milliseconds later.

There are various ways to solve this, but the basic idea would be to cancel the submit event straight away if the check hasn't been done, do the check, and then submit the form again if the email didn't exist, and not run the check the second time.

Here's something a bit ugly that I think'll work, but it can be done much more elegantly, I'm sure:

var emailWasChecked = false;

$("#form").on('submit', function (e) {
    if (!emailWasChecked) {
        e.preventDefault();

        $.post('?ok=1', {
                action: 'formerly/submissions/alreadySubmitted',
                formid: $("input[name=formId]").val(),
                email: $("#formtest_email").val()
            },
            function (data, status) {
                if (data.alreadysubmitted != true) {
                    emailWasChecked = true;
                    $("#form").trigger('submit');
                }
            });
    } else {
        emailWasChecked = false;
    }
});


I'm afraid you can not. But a bit of PHP and the plugin store's API url shows you the list of plugins of which the first edition is free (or go to this page):

<?php

 $perPage = 100;
 $page = 1;

 $done = false;
 while (!$done) {
   $url = 'https://api.craftcms.com/v1/plugin-store/plugins?perPage=' . $perPage . '&page=' . $page . '&orderBy=name&direction=asc';
   $response = json_decode(file_get_contents($url));

   if (isset($response->plugins) && !empty($response->plugins)) {
     foreach ($response->plugins as $plugin) {
       if ($plugin->editions[0]->price === null) {
         echo '' . $plugin->name . '
';
         echo $plugin->shortDescription . '
';
         echo 'handle . '" target="_blank">Show me more

';
       }
     }
   }

   if ($response->totalResults <= ($perPage * ($page))) {
     $done = true;
   }

   $page++;
 }


Loop through all possible options of a Dropdown-field

{% for option in entry.dropdownFieldHandle.options %}

{{ option }}

{% endfor %}

That should be it :)

{% for entry in craft.entries.section('sectionname') %}
  {% for option in entry.dropdownFieldHandle.options %}

{{ option }}

  {% endfor %}
{% endfor %}

Use the above if it is only one page

{% set myArray = [] %}

{% for entry in craft.entries.section('sectionname') %}
  {% for option in entry.dropdownFieldHandle.options %}
        {% set value = option %}

        {% set myArray = myArray|merge([value]) %}
  {% endfor %}
{% endfor %}

And loop over that variable , better to load 1 variable as array if you need it over multiple pages. Just make sure all pages have access to this variable (or create a macro for it)


Best way to implement my own statuses on my custom element type?

All you need to return from the getStatuses() method is an associative array() where the key represents the status name and the value represents the status label, more or less.
An example might be a set of statuses for a Payment element type:
public function getStatuses()
{
    return array(
        'captured' => Craft::t('Captured'),
        'canceled' => Craft::t('Canceled'),
        'refunded' => Craft::t('Refunded'),
    );
}

Now, since it is likely that you'll be referring to and comparing against those statuses, it makes sense to give yourself a little extra insurance by creating a set of class constants instead of using plain strings.
That is exactly what Craft has done in the UserStatus class and you can achieve the same result in one of two ways.

1. Create your own class and define those constants
// plugin/enums/PluginPaymentStatus.php
namespace Craft;

class PluginPaymentStatus
{
    const CAPTURED = 'captured';
    const CANCELED = 'canceled';
    const REFUNDED = 'refunded';
}

// plugin/elementtypes/PluginElementType.php
public function getStatuses()
{
    return array(
        PluginPaymentStatus::CAPTURED => Craft::t('Captured'),
        PluginPaymentStatus::CANCELED => Craft::t('Canceled'),
        PluginPaymentStatus::REFUNDED => Craft::t('Refunded'),
    );
}

2. Create the status constants in your element type model if you have one

Note that if you go with option 1, you will need to import|include|require your "enum".


I don't know what your specific error is, but whenever I use

Event::on(
\craft\elements\User::class,
\craft\elements\User::EVENT_AFTER_SAVE,

I need to provide the next parameter with a \yii\base\Event callback, not a \craft\events\ModelEvent one.

Maybe that's your case as well ?
 You can also use \yii\base\ModelEvent, but not the craft one, as the craft ModelEvent does not extend \yii\base\Event


There are several reasons (mostly environmental) why a person would be logged out from the CP discussed in these posts (along with fixes/workarounds):

Craft constantly logging out from admin area

Migrated Server, Now Getting Logged Out Constantly

Keep on getting logged out when deploying using Capistano

Users are always logged out on front end

Load Balancing Craft CMS - Admin gets logged out instantly

I'd start by reviewing those.

  and sometimes the words 'unknown error' pop up.

My hunch is it's related to your session issues, but you can check your craft/storage/runtime/logs folder for the underlying error message.

Also related and may be helpful:

The Case of the Missing PHP Session


Try swapping the order of your Routes (drag and drop), so that specific resources are routed first and the homepage fallback is positioned second.

Routes are applied in the order the appear in Settings > Routes i.e. If a route criteria is matched then Craft doesn't seem to try the rest.

More info here: https://craftcms.com/docs/routing just in case you haven't seen it already.

Let us know if that helps.


Solution:

{% if block.myFormField|length %}
    {{ block.myFormField.first().displayForm() }}
{% endif %}


Plugin development - Adding Foundation 5 CSS changes Craft CMS control panel

I don't use Foundation 5. I've been using Foundation 6, but I'll offer a suggestion based on Foundation 6 usage.

It looks like your Foundation CSS is overriding the base Craft control panel CSS, specifically the button classes.

My guess is that because you're including all the Foundation classes available. If you're using the SASS version, you can comment out the parts you aren't using to minimize the size of what you're using from the base Foundation code. For example, you can try to exclude the button classes from Foundation.

Specifically, if you remove the .button styling rules from your foundation.css file, the Craft buttons would go back to normal.


entry edit no other content area unless title?

You need to add the fields to the section.
If you go into Sections then over at the right side you can edit the entry type there.
Drag the fields up to the top area to select the fields for that entry.

See https://docs.craftcms.com/v3/sections-and-entries.html#entry-types


When you use {% paginate %}, the second variable that's returned, pageEntries, is  the paginated entries. When you do craft.entries.section('news').featured('not 1') later in the template, you're doing a new query that's not paginated.

Assuming what you want is to return all featured entries at the top, then a paginated list of news below, try something like this:

{% extends "_layout" %}
{% set title = "News" %}

{% paginate craft.entries.section('news').featured('not 1').limit(5) as pageInfo, pageEntries %}

{% block content %}

Company News

        {% for featuredEntry in craft.entries.section('news').featured('1') %}

                    {% for image in featuredEntry.featuredImage %}

                    {% endfor %}

{{ featuredEntry.title }}

                    {{ featuredEntry.body.getPage(1) }}
                    Continue reading

        {% endfor %}

        {% for regularEntry in pageEntries %}

{{ regularEntry.title }}

                    {{ regularEntry.body|hacksaw(words='25', allow='
') }}
                    Continue reading

        {% endfor %}

        {% if pageInfo.prevUrl %}Previous Page{% endif %}
        {% if pageInfo.nextUrl %}Next Page{% endif %}

{% endblock %}

If additionally, you only want to show the featured entry on the first page, you could wrap the first for loop in:

{% if pageInfo.currentPage == 1 %}
    ...
{% endif %}

More details on pagination in the docs.


How to route short tag to external web site

With the registerSiteRoutes hook you can route http://short.com/e9DG requests to any template.

public function registerSiteRoutes()
{
    return array(
        'e9DG' => '/mysection/mytemplate.html',
    );
}

With getUrl and redirect accessible via craft()->request you can set up server redirects:

$url = craft()->request->getUrl();

if ($url == 'http://short.com/e9DG')
{
    craft()->request->redirect('http:/longdomainname.com/longsubpagename', true, 301);
}


Is it possible to display additional fields on the entries list in admin?

Yes, since Craft 2.3 you can edit the CP's index views for entries, assets, etc. from a plugin.

Have a look at the documentation for the hooks defineAdditionalEntryTableAttributes and getEntryTableAttributeHtml to see some sample code. Making a little plugin for this is easy, simply copy and paste the above sample code into your primary plugin class and then edit the parameters.


Assets (in assets folder) failing to load locally [Craft 2]

My guess is that your bucket doesn't have the right permissions. Try adding this permission to your bucket (use with caution since this will make the S3 100% public):
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::bucketname/*"
        }
    ]
}

Replace bucketname with your actual bucket name. You can add this policy via the AWS UI console. In S3 > YourBucket > Permissions > Bucket Policy.
If by doing this you actually manage to get URLs that resolve, then your problem are permissions. I would still delete this bucket policy and set the correct permissions for your use case.


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

You're getting that error message because there is an existing craft/config/license.key file in place for your local installation and there is no record of that install on the Craft/web service end.  Likely you've just copied an existing license.key file from another site into this new installation.

So the web service on the Craft end thinks that since it's a new Craft client installation it needs to send down a new license.key file for you to start using.  But the Craft client knows it should never overwrite an existing license.key file, so it reports that error.

Solution: remove the existing license.key file (since it probably belongs to another site anyway) and let the web service generate a new one for you.


How do you manage your Craft 'starting point'?

I have a Craft boilerplate installed on my local machine - like a self-contained website with all the stuff I use on every project (I also keep my front-end framework in here).

When I start a new project:

Duplicate the boilerplate site folder
Create an entry in MAMP
Delete the .git folder
Duplicate the local database for the new site (SequalPro, Navicat)
Delete /craft/config/license.key

Bingo, new site is ready to go with all the fields and front end stuff I need for a new project.


How to automatically redirect a url based on dynamic content

Take a look at Craft's redirect function:

{% redirect '/' %}

In your case it would look like this:

{% redirect 'neptune/' ~ id ~ '/confirm' %}


Type php --ini in your server environment, it should tells you where the .ini files are getting loaded.
Then set
allow_url_fopen = 1


Find structure entries which parents relate to other entries

Yes, it looks like the descendantOf param doesn’t accept an array of element models or array of element IDs. Here’s what you can do in Twig to work around the problem.

This solution does trigger an additional query for every parent entry matching your relatedTo criteria. But as it’s only fetching the ids column, it might not perform too bad actually, depends on the amount of matching parent entries though.

{% set idsParam = [] %}
{% for parent in parents %}
    {% set idsParam = idsParam|merge(parent.getDescendants().ids()) %}
{% endfor %}

{% set children = craft.entries({
    section: 'training',
    ids: idsParam,
    eventDate: '>= ' ~ now|date('U'),
    order: 'startDate DESC',
}) %}


You can do this with Craft’s {% redirect %} tag. Just put this in your /index.html template:

{% redirect 'news' %}

If you want to redirect to the latest entry in your News section, as you mentioned in the comments above, just fetch the entry first:

{% set latestNews = craft.entries.section('news').order('postDate desc').first() %}
{% redirect latestNews.url %}


Resource for setting up Craft CMS Fields

This is a brain dump of learning resources I can think of.

There's the official documentation.
Straight Up Craft has some great learning articles and tutorials.
They also happen to have the most comprehensive list of Craft plugins until the official plugin store becomes a thing.
The Craft site also has help articles and tutorials.
The online Craft demo site running Happy Lager.
The Happy Lager repo if you'd prefer to setup locally.
This Craft Stack Exchange site for Q&A.
The Craft Slack group with people on from around the world practically 24x7.
The Craft feedback site to see if a feature you'd like to ask for has already been asked.
Sites like Craft Cookbook for help with Twig and templating recipes.
Twig's documentation for more Twig help.
Mijingo has many Craft-specific video tutorials both free and commercial. Also, there are articles and more.
There are many user generated Craft video tutorials up on YouTube.
craftlinklist.com is a periodic newsletter where you can sign up for a curated list of Craft resources from around the web.


How to add HTML, CSS, JavaScript on the front-end using a template hook in a plugin?

In your plugin's main file init method setup your template hook. In this hook you can call a service method to return your rendered HTML.

public function init()
    {
        craft()->templates->hook('video.slider', function(&$context)
        {
            $response = craft()->pluginname_service->serviceMethod();
            return $response;
        });
    }

In your plugin's service file create a method to return your rendered HTML.

function serviceMethod()
    {

        $oldPath = craft()->path->getTemplatesPath();

        $newPath = craft()->path->getPluginsPath().'path/templates/folder';
        craft()->path->setTemplatesPath($newPath);

        $templateName = '_templatename';

        //If you need to get data from somewhere else to pass to the template
        $htmlData = craft()->plugin_service->serviceMethod();

        $htmlResponse = craft()->templates->render($templateName, array("variableName" => $htmlData));

        //reset path
        craft()->path->setTemplatesPath($oldPath);

        return $htmlResponse;
    }


Edit select dropdown field in a Matrix on the front-end

I was struggling with the same issue. Using your code I was able to get the select box to update by removing the [] at the end of your select name variable.

So this code wasn't working

<select class="form-control" type="text" name="fields[userDivingCertification][ {{ block.id }}][fields][certificateType][]">

but changing to

<select class="form-control" type="text" name="fields[userDivingCertification][ {{ block.id }}][fields][certificateType]">

got it submitting correctly.

The other issue I was having with the data being wiped completely was due to the hidden type field not having the correct value. I had copied some code from elsewhere and forgot to change the value. Once I got it matching my Matrix Block Type handle it worked fine.


That contains test just does a smple string comparison. Try this:

{% if entry.pageOptions.contains('anotheroption')
     or entry.pageOptions.contains('testimonials') %}


Hosting Craft on Heroku, problems with Asset uploads and thumbnail generation

I solved the problem by setting the client_max_body_size to, in my case, 20M.

Did this using the following nginx_app.conf

location / {
    # try to serve file directly, fallback to rewrite
    try_files $uri @rewriteapp;
}

location @rewriteapp {
    # rewrite all to index.php
    rewrite ^(.*)$ /index.php?p=$1 last;
}

location ~ ^/(index)\.php(/|$) {
    client_max_body_size 20M;
    fastcgi_pass heroku-fcgi;
    fastcgi_split_path_info ^(.+\.php)(/.*)$;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param HTTPS off;
}


Error while trying to use dynamic routing to pass variables to the template and using them

Try this:

{% set category = craft.categories(segmentCategory).first %}

Without the first at the end, you're setting category to an ElementCriteriaModel. Which would be fine in many cases, but it's not an acceptable variable type for targetElement.

Ditto for the sourceElement:

craft.entries.section(segmentEntryType).status(null).first


Directories and files being created by "root" user, inaccessible to CMS

I'm assuming the web server isn't running as root:root.  The normal cause of this is someone SSH/(s)FTP'ing into the box as root:root and executing some command (directly or with sudo) that generate files on the file system that are owned by root.


How do I save a Matrix field with an asset block programmatically?

This ended up being a Craft bug. We just released Craft 2.1 build 2562 with a fix.


Bootstrap 4 Accordion with Matrix (and SuperTable)

I'd break up the forloops a bit so you're outputting the panel container and the accordion wrapper markup once. Then for each accordion (supertable row) you're outputting that markup as many times as it's needed.

I haven't used Bootstrap JS packages for a long time, so I was a bit thrown by the amount of divs you have. (I use this accordion package for how simple it is. It's an oldie, but a goodie and is still being maintained.)

{# Matrix loop of blocks #}
{% for row in entry.contentBuilder.all() %}

    {% switch block.type.handle %}
    {% case 'accordion' %}

                         {# Supertable loop of accordions #}
                         {% for block in row.components.all() %}

                                         <button class="btn btn-link" data-toggle="collapse" data-target="#collapse{{ loop.index }}" aria-expanded="true" aria-controls="collapse{{ loop.index }}">
                                              {{ block.accordionTitle }}
                                          </button>

                                         {{ block.accordionCopy }}

                        {% endfor %}

    {% endswitch %}
{% endfor %}


Wasn't sure if I need to also setup a field type entries in GamePublishers to reference to Games section.

Not necessary if you already have a "GamePublishers" Entry field in the "Games" section.

Something like this should work:

{% set games = craft.entries.section('games').relatedTo(publisher) %}

That's assuming you've already got a variable named publisher defined that's referencing the current publisher the user is viewing.

I'd suggest reading through the relations docs as well.  Craft has a pretty powerful relations engine you can do all sorts of crazy stuff with.


Twig's 'start with' conditional returns 500 error

I was able to reproduce this without the starts with, and editing the usual PHP settings which cause problems with uploading assets sorted this out.


How to render plugin templates in Craft CMS 3?

After becoming more familiar with Craft and Yii, I've found a more appropriate solution for my use case. I have a couple of ideal requirements:

Templates are stored in a directory within my module or plugin.
Templates can be mixed with general application templates (e.g. my module or plugin template can extend from a general site layout template).

It turns out that the Template Roots functionality enables this, so it is documented but for some reason I was overlooking this previously.

You can simply register the template root during plugin/module init like so:

Event::on(View::class, View::EVENT_REGISTER_SITE_TEMPLATE_ROOTS, function (RegisterTemplateRootsEvent $event) {
   $event->roots['_my_prefix'] = __DIR__ . '/templates';
});

Then templates in the defined directory can be rendered using the defined prefix (_my_prefix in this case), as though that directory exists in the main templates directory. This means they can be used in any context and extend or include templates in the main directory ‒ desirable for app specific plugins/modules.


Craft ships with PHPUnit... How can we use it to test our plugins?

Yes it is possible, see this example plugin by Selvin Ortiz: https://github.com/selvinortiz/craft.loath.

You can also check out https://github.com/boboldehampsink/import for some detailed unit tests.


Can the Craft CMS admin be blocked from accessing the Internet?

Instead of blocking the CMS's access to the internet, you should consider firewalling access to the CMS from the outside world. Basically, block all incoming IP addresses but your own. I can understand your need for security, but the CMS's core functionality relies on being able to communicate with the outside world to keep the system updated.

If you block access as you're wanting to do, I think you will find that it's going to be much more difficult to manage the system. Things that come to mind:

You'll need to be able to keep the system updated with source control (eg. Git) which requires internet access.
If you get into a situation where an update fails in the CMS, you may need to  run Composer via command line on the server. This will require the internet to update packages.
One of the best ways to manage assets (images) in CraftCMS is to use a CDN like Amazon S3. You'll get much better site performance with a CDN. If your server cannot communicate with the internet, you'll lose this ability.

I'm sure there are many more ways that you'd essentially be hobbling the system. I'm not directly answering your question here (which I would prefer to do), but instead I'm trying to dissuade you from creating a system that is unmanageable.

UPDATE

As I began thinking about this more, I came up with a few more things to consider:

Keep your CraftCMS site files on a server that has access to the internet, and connect it to a database on a server which has no internet access. I did this for a previous client using Rackspace's Rackconnect which is essentially a back-door network that is only accessible to other Rackspace servers. I'm not sure how you host, but I'm sure this can be done with other service providers. At the end of the day, what you really want to protect is the contents of the DB.
Set up a VPN and require that users authenticate to the VPN before being able to connect to crucial protocols like SSH. I had this scenario set up for a previous client as well. Essentially, you must establish a VPN connection first, then you can SSH into the server.

Caveat, I'm not a server security person. I've set up a bunch of servers, and learned along the way what makes good security from people smarter than me. Your IT people may have even better suggestions than what I've provided.


It's probably because entry.dayOfEvent isn't returning exactly what "now"|date_modify('+1 day') is returning therefore the comparison fails.  Maybe one includes the time and the other doesn't, for example.

You can see what each is returning by doing:

{{ entry.dayOfEvent }}
{{ "now"|date_modify('+1 day') }}

If they are different formats, then you can make the 2nd one match the format of the first by using Twig's date format method.


Craft on Heroku is not logging. How can I make it start?

There is a plugin that redirects all of Craft log output to stderr that works on Heroku and Fortrabbit.

https://github.com/ostark/craft-stderr-logger


Register a user as part of a Commerce checkout?

Luke's answer above is absolutely right and the simplest approach, but as I commented above, I wrote a plugin for this:

https://github.com/bossanova808/CommerceRegisterOnCheckout

..the reason being that I wanted to integrate registration during the checkout, not after as Luke has done above.  And the motivation for this is that site registration rates plummet (like, by 80%+ in my totally anecdotal data/experience) - if the registration comes AFTER checkout.  We get a MUCH higher rate of people joining (which has all sorts of business benefits for us) - if we integrate it right IN to the checkout flow.  I can't say why that is precisely, but it seems like most folks mentally check out (excuse the pun) the moment they hit 'Submit Order'....

So I wrote the above to allow a more integrated approach, which does much as what you describe - there's an ajax POST but it's during the payment part of the process (i.e. the actual checkout but), and the user is then registered & logged in (and can e.g. be taken then automatically to their orders summary page).  If there is any failure in registration (e.g. they've forgotten they registered before) - we handle that and present whatever we need to (including possibly a pre-filled registration form for them to have another go with).

(BTW I agree - this should definitely be supported by Commerce in core).