First problem sounds like it might be a permissions issue. Have you made sure you've got the right permissions on the /craft/storage folder? More details can be found here in the docs:

Step 2: Set the permissions

Possibly related to the above, did you originally use name and then updated it to title at a later time? One possible reason for your deprecated messages might be the template is cached with the old name value. Sorting out the above should at least enable you to clear the cache, using the Clear caches button in the Settings.


Notes field only for certain product types

I think you can do something like;

{% if product.type('products') %}
    code to show notes field
{% endif %}

See the product model docs here https://craftcommerce.com/docs/product-model

The note attribute is part of the lineitem model so you should be able to show it.

https://craftcommerce.com/docs/line-item-model#note

The following should work.

{% for item in order.lineitems %}
    {{ item.note }}
{% endfor %}

You could try naming your input field like so;

<input class="form-control" type="text" placeholder="Productsort"  name="item[note]" value="{{ item.note }}" required>

I'd need to test this though. I've done something along these lines but can't remember exactly what I did.


{% if entry.postDate > now|date_modify("-1 month") %}
    {# Output #}
{% endif %}


How to duplicate entries and loop them without getting a Twig or deprecation error?

Instead of duplicating the entries, you could run your entries loop twice (or as many times as you want) maybe?

{% for i in 0..1 %}
    {% for entry in entries %}
        {{ entry.title }}   <br>
    {% endfor %}
{% endfor %}


Thanks to brad I got the whole thing working.
Here's the stripped down code:

{#

    Get all Dates from within the table field in the section veranstaltungen
    ------------------------------------------------------------------------
    We have a section called veranstaltungen with a table field that contains dates and times
    In order to get all occurences of the dates wihin the table field, we first get all of the
    table dates and attach the entry to each table date.
    Then we sort this array (dates) first by day and within a day by time.

    This is a simple Calendar without the need for a plugin.

#}
{% set entries = craft.entries({
    section: 'veranstaltungen',
    with: [
        'cf_veranstaltungs_cat',
        'cf_veranstaltungsDatum_table',
        'cf_veranstaltung_asset',
        'cf_veranstaltungsLinks_table',
        'cf_veranstaltungs_assets',
        'cf_coVeranstalter_user'
    ],

    relatedTo : relation_param,
    authorId: veranstalter_param|trim,

    limit: null
}) %}

{#
    The dates Array will contain all occurences of the entries - we will order it first by date and then by time
#}
{% set dates = [] %}

{% for entry in entries %}

    {% set table = entry.cf_veranstaltungsDatum_table %}

    {% for row in table if row.startDate %}
        {% set dates = dates|merge(
            [{
                'date': row.startDate|date('Y-m-d'),
                'time': row.startTime|date('G'),
                'startDate': row.startDate,
                'startTime': row.startTime|date('G:i'),
                'endTime': row.endTime|date('G:i'),
                'entry': entry,
                'links': entry.cf_veranstaltungsLinks_table,
                'image': entry.cf_veranstaltung_asset,
                'files': entry.cf_veranstaltungs_assets,
                'categories': entry.cf_veranstaltungs_cat ?? null,
                'categoryColor': entry.cf_veranstaltungs_cat[0].cf_veranstaltungsCatColor ?? null,
                'categoryIcon': entry.cf_veranstaltungs_cat[0].cf_veranstaltungsIcon_asset.first.url ?? null,
                'author': entry.author,
                'coVeranstalter': entry.cf_coVeranstalter_user,
                'id': entry.id,
            }]
        ) %}
    {% endfor %}
{% endfor %}

{#
    ------------------------
    Veranstaltungen Listing
    ------------------------
#}

    {% set datesSortedByDay = dates|group('date')|supersort('ksort', 'date') %}
    {% for key, day in datesSortedByDay %}

{{ key|date('l, d. F') }}

        {% for date in day|supersort('sort', 'time') %}
            {% include "veranstaltungen/_common_tableDates" %}
        {% endfor %}
    {% endfor %}

Crazy what you can do with twig!


PHPUnit - Warning: "Header already sent"

You could try setting PHPUnit's @runInSeparateProcess flag, as discussed here.

However, it sounds as though you're attempting to use PHPUnit for acceptance or integration tests, when it's really designed to be used for unit testing.

A couple of options:

You could mock the JsonHelper::sendJsonHeaders method, but that may prove tricky;
You could use something like Behat for integration testing. This may be more appropriate for a controller.

Stephen


This is fixed in 3.0.0-beta.10. Additionally you can use the concept of aliases in your URL for all sorts of variables:

@web/assets/data/clients.xml

Which would be related to your web root.


Proper way to implement array of objects as Craft field

Probably you would want to use:

Users field as a relation to one or more of the users
Categories field as a relation to one or more of the categories


Yup, that's correct. The craft_elements.dateCreated column is the one that is referenced by the user's Join Date.

For the sake of being thorough, I prefer to copy that same value into craft_users.dateCreated, just as you have done.


Getting admin to work on a "dev-sounding" subdomain

As Luke referenced in his answer, you're mixing up two separate (but related) concepts.

Craft License

Your license key is stored in your craft/config/license.key file. This file is automatically generated the first time you run Craft, and should always remain a part of your website. If you're using version control, make sure that it's included in your repo.

Craft Edition

The "edition" of your website refers to which version you're using: Free, Client, or Pro.

Whichever edition you are currently using will be stored in your database for immediate reference... However, your site will frequently ping Pixel & Tonic's servers to ensure that it's using the correct edition. While your license key does not directly contain which edition you should be using, it let's P&T's servers know which website is performing the request, and replies back with the proper edition information.

How it relates to your situation...

Using a "dev-sounding" domain name only does one thing:

You can share the same license key file between domains without getting a warning message at the top of each page.

The P&T servers will associate your license with only the non-dev-sounding domain... any dev-sounding domains will not be recording with your license key data. So if you try to use the same license key file on multiple non-dev-sounding domains, all but one will display this message:

  The license located at config/license.key belongs to [OTHER DOMAIN]. Transfer it to this domain?

In regards to your edition... As long as they're sharing the same license, every environment for your site will share the same edition.

As Luke mentioned, when developing a site in your local environment, you can set the local path to end with craft.dev. This is considered a very special circumstance... Craft will recognize this special domain and allow you to upgrade your edition for free!

Of course, since that special domain is only available locally, you'll be expected to properly purchase your edition when you move your site to any other domain name (regardless of whether it's "dev-sounding").

Again, Luke's solution is correct... Purchase the license now, and don't worry about what the final domain will be. It's not relevant. Switching your license to the correct domain is incredibly easy and painless, and happens with a single click.

UPDATE:

It's now possible to try Craft Pro from any non-public domain:

  http://pixelandtonic.com/blog/test-craft-client-pro-from-any-non-public-domain


Here's a Mijingo resource that should help: https://mijingo.com/blog/manually-installing-craft-3


The front-end of a Craft site is 100% custom and leaves you with complete control over the HTML, CSS, JS and images that are generated, so there's really no way for us to give you step-by-step instructions on how to make specific changes to the front of your site

Generally speaking, you can modify the HTML and content of your site from the craft/templates folder on your server.  Any CSS/JavaScript/images on your site will likely live in your public HTML folder on your server.


I simply deleted everything and re-uploaded and it worked. It must have been a corrupt upload because I'm up and running now. Thanks!


Load a specific file/CSS only in a certain page

You can register your file with Twig at the place you need it

{% do craft.app.getView().registerCssFile(alias('@assetUrl') ~ '/path/to/css') %}


Make sure that you checked Use this field’s values as search keywords under Settings → Fields → Your field
With that in place, run ./craft resave/entries --update-search-index (docs) and your entries should start showing up in your search results.


Output Radio or Checkboxes with A+M Forms

I'm confused by what you mean by "output". Do you mean: how do you write custom HTML for checkboxes or radio buttons and have them submit to amforms?

If that's the case, you need to understand the name attribute always needs a fields[] array. StraightUpCraft has a great rundown of how all field types' name attributes should be formatted in order to submit to Craft, no matter if you're using amforms, Sprout, or whatever.

Radio Buttons

Radio buttons are a "single option field", meaning that when the form submits, only one value goes through. Your code should look like this (I stripped out some of the unnecessary markup):

<label>Choose an option
    <input type="radio" name="fields[fieldHandle]" value="Option 1"> Option 1
    <input type="radio" name="fields[fieldHandle]" value="Option 2"> Option 2
    <input type="radio" name="fields[fieldHandle]" value="Option 3"> Option 3
</label>

Checkboxes

Checkboxes are "multi option fields", meaning that when the form submits, any number of values can go through, so you need to submit them a bit differently:

<label>Choose your class type
    <input type="hidden" name="fields[fieldHandle]" value="">
    <input type="checkbox" name="fields[fieldHandle][]" value="Option 1"> Option 1
    <input type="checkbox" name="fields[fieldHandle][]" value="Option 2"> Option 2
    <input type="checkbox" name="fields[fieldHandle][]" value="Option 3"> Option 3
</label>

Pay close attention to each input having an extra [] at the end and the hidden input that collects all their values into a final array.

One very important note

You absolutely need to make sure the values of each input you have in the HTML equal the values you created in the CMS when you created the field. This includes capitalization and spaces.  So if your checkbox field in the CMS, for example, had a handle of breakfast, and each option's Label/Value was set like

French Toast | French Toast
Ham n' Eggs  | ham-n-eggs
Corn Flakes  | c0rnFlaaaake$$

then your input values need to match exactly:

<label>Breakfast Options:
    <input type="hidden" name="fields[breakfast]" value="">
    <input type="checkbox" name="fields[breakfast][]" value="French Toast"> Option 1 (this text can be anything)
    <input type="checkbox" name="fields[breakfast][]" value="ham-n-eggs"> Option 2
    <input type="checkbox" name="fields[breakfast][]" value="c0rnFlaaaake$$"> Option 3
</label>

Craft's expecting these to line up, and if they don't, then either these fields' values will be ignored on submit or, if the field is set to required in the CMS, you'll get a back-end validation error.


Thumbnails broken in CP after migrating images to AWS S3

My first guess would have been that the asset indexes stored in the database are out of sync since it was recently migrated to a new Volume.

A way to fix that would be to run the "Update Asset Indexes" utility from the Control Panel.


How can I display second level children only from a specific parent structure item?

yes you can!

You may search for a slug craft.entries.slug('slug-of-first-parent'), select the first result .one(), and then the children by .getChildren(). Now you can proceed as you already did and limit your result to only elements with a level greater than 1 .level('>1') and list.

{% set pages = craft.entries.slug('slug-of-first-parent').one().getChildren().level('>1') %}

I am not sure whether this is the best and most effective solution, but it should definitely do the job.

Tip: You can display information about an entry and the methods and variables available by dumping them either by using var_dump($variable) in php code or {{ d($variable) }} (by using this free plugin) in your twig template. This can help a lot when dealing with entries and finding children or parents.


How do you filter matrix blocks by type?

You can grab a specific block type in Matrix by doing this:

{% for block in entry.myMatrixField.type('typeOne') %}
    {{ block.text | markdown }}
{% endfor %}

If you wanted to know the number of blocks of a certain type, you can do:

{% set blocks = entry.myMatrixField.type('typeOne') %}
{{ blocks | length }}

If you want to search for multiple block types, you can do this:

{% set blocks = entry.myMatrixField.type('typeOne, typeTwo') %}

For your specific example, it would look like this:

{% set typeOneBlocks = entry.myMatrixField.type('typeOne') %}

{% if typeOneBlocks | length %}

        {% for block in typeOneBlocks %}

{# do stuff #}

        {% endfor %}

{% endif %}


Only fetch categories that are related to a minimum of entries

What you can always do in situations, where the default parameters are not enough,
is to "collect" element IDs and pass them to the id param of a new criteria model.

So loop through all categories and merge the category IDs matching you condition to an array:

{% set topCategoriesIds = mainCategoriesIds|merge([category.id]) %}

When you're done, get your filtered categories from these IDs:

{% set categories = craft.categories.id(topCategoriesIds) %}


How to link to a page, but only if the page status is active

This should work.

{% set policy = craft.entries.section('policy').first() %}
{% if policy %}{{ policy.title }}{% endif %}

ElementCriteriaModel should only return active records by default.


onBeforeDeleteCategory not working / inconsistent

Neither onBeforeDeleteCategory nor onBeforeDeleteElements has a $performAction parameter that you can set to cancel the event, which would behavior #2 you're seeing.

The first behavior you're seeing can be explained by this, which you've already found the workaround for.  FWIW, that's changed for the upcoming Craft which, which behaves more as you'd expect now.


Posting to plugin's action controller using Ajax + JSON

In your newsletter form, you should have:

<input type="hidden" name="action" value="mailchimp-subscribe/audience/subscribe">
<input type="hidden" name="language" value="{{ craft.app.locale.id }}">

Then, you should POST to '/' + userLocale (where userLocale = $('[name="language"]').val()).

I am using jQuery, and this is working fine:

$.post({
    url: '/' + userLocale,
    dataType: 'json',
    data: $('#form').serialize(),
    success: function(response) {
        console.log(response);
    },
    error: function(response) {
        console.log(response);
    }
});


Programmatically Setting Entry Type Via Javascript

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

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


Redactor air not visible when code mirror is enabled

I found a quick solution to show toolbar when hover code mirror

 callbacks: {
   init: function() {
   $('.CodeMirror-scroll').on('hover',function(){
         $('.redactor-air').css('display','block');
          });
       }
}

But the issue is the same when i have more then one redactor in same page, because it shows both toolbar...

Any help on this ?
Thanks


Since Twig is server-side, and Javascript (usually) is client-side, you would need to change your code's logic so that the desired value you need inside that Twig command can be injected using javascript on the client's side.
Then you could send that data back along with the rest of the submission.
If you need server-side javascript, you would want to look at node.js


Have you tried?:

 {% set upcoming = craft.entries.section('gigEntry').status('pending', 'live').gigDate('>= ' ~midnight) %}


How can I display fields from Field Layout Designer in the template?

Ok so I finally got it going with the help of that Inspector plugin. This is what I did..

In my front end template..(i used index.html)

{% extends "_layout" %}

{% import "_includes/forms" as forms %}
{% set form = craft.formBuilder.getFormByHandle('testTwo') %}
{% set fields = form.fieldLayout.getFieldLayout().getFields() %}

{% block content %}
<div class="container">

{% for field in fields %}
  {% set input = craft.fields.getFieldById(field.fieldId) %}
  {% set requiredInput = field.required %}

  {% include "_includes/field" with {
    field: input,
    required: requiredInput
  } only %}
{% endfor %}

</div>
{% endblock %}

Explanation:

Each form will have a formHandle name. With the following line I can target that form in the template (see screenshot 1)..

{% set form = craft.formBuilder.getFormByHandle('testForm') %}

Each form has a fieldLayout Builder so I now need to get the fieldLayoutId associated with the form above. While I'm getting the fieldLayoutId I will ask for fieldId's associated with this fieldLayoutId..The bellow will let me get fieldId (also see screenshot 2 in my question, basically the following line lands me on that table)

{% set fields = form.fieldLayout.getFieldLayout().getFields() %}

Now that I have fieldId's I can use the following line to get all my fields!

{% set input = craft.fields.getFieldById(field.fieldId) %}

I'll need to include that inside my for loop so I can render all the fields.

There is more work for what I need to achieve in this plugin, but this was biggest obstacle for me personally so hope this helps someone too. Thanks for help and info on the Inspector plugin.

Note

There are 2 folders you will need to copy from craft/app/templates/ directory into your craft/templates/ directory.

_includes and _components


I'm not exactly sure how this plugin works, but in general the best way to do this is to rely on Webhooks.  You can listen for charge.succeeded events and send an email when those occur.  If you're not a programmer, you can always use something like Zapier or IFTTT to do this too.

:)  Hope that helps!


100% untested, but try this:

return [
    'endpoints' => [
        'api/jobs.json' => function() {
            HeaderHelper::setHeader([
                'Access-Control-Allow-Origin' => 'http://example.com'
            ]);

            return [
                'elementType' => 'Entry',
                'criteria' => ['section' => 'jobs'],
                'transformer' => function(EntryModel $entry) {
                    return [
                        'title' => $entry->title,
                        'url' => $entry->url,
                        'jsonUrl' => UrlHelper::getUrl("jobs/{$entry->id}.json"),
                    ];
                },
            ];
        },
        'api/jobs/<entryId:\d+>.json' => function($entryId) {
            HeaderHelper::setHeader([
                'Access-Control-Allow-Origin' => 'http://example.com'
            ]);

            return [
                'elementType' => 'Entry',
                'criteria' => ['id' => $entryId],
                'first' => true,
                'transformer' => function(EntryModel $entry) {
                    return [
                        'title' => $entry->title,
                        'url' => $entry->url,
                        'entryId' => $entry->id,
                        'postDate' => $entry->postDate,
                    ];
                },
            ];
        },
    ]
];


Extending the Users section of the admin panel

Right now you're best bet is going to be with a plugin that has its own, separate section for displaying the purchase information.


Freeform Lite update on Craft 2 deleted tables

But on my remote server it deleted two thirds of the tables in the db.

That sounds like some update failure happened, Craft tried to roll-back and restore the database from its pre-update attempt database backup because https://docs.craftcms.com/v2/config-settings.html#restoreDbOnUpdateFailure is set to true, then plot twist another failure happened before it could restored and left the database in an inconsistent state.

There are tons of reasons an update might fail to go through, and nearly as many for why a restore would fail, but a good place to start would be your craft/storage/runtime/logs files as well as your web server's log files.


How can I get the count of entries in a structure?

There may be a better option, but off the top of my head, you could do:

{% set countParent = craft.entries.slug('oakview-hotel').first() %}
{% set count = craft.entries.section('hotelDetails').descendantOf(countParent).level(3).type('review').total() %}
        {{ count }}


I just figured out what caused the problem.

When changing from freeform 2.x to 3.x one has to change the wording in the composer.json from "solspace/craft3-freeform" to "solspace/craft-freeform" (delete the "3".


The other error Im getting is dirname: command not found.
I was able to solve this issue by just manually setting the DIR variable in the script I needed to use. There is probably a better way....


Filtering multiple categories with URL queries

The issue with your current code is that you're looping over each type/size category, creating a parameter in your relatedTo query for each one. This means that you're currently creating a query that looks like this:

relatedTo([
    'and',
    { targetElement: 1 },
    { targetElement: 2 },
    { targetElement: 3 },
    { targetElement: 4 }
])

...which, combined with the AND, means that Craft will only return entries that have all of these relations.

What you need to do, is to collect the IDs for each category group in an array, and add those arrays to the relatedTo query – i.e. create a query that looks like this:

relatedTo([
    'and',
    { targetElement: [1, 2] },
    { targetElement: [3, 4] }
])

The above query would solve your issue, because whenever Craft isn't given an and or or, it assumes or. This means that the above query is exactly the same as the below:

relatedTo([
    'and',
    { targetElement: ['or', 1, 2] },
    { targetElement: ['or', 3, 4] }
])

Essentially, the above query is saying: give me all entries that have a relation matching either the target element 1 OR 2, AND a relation matching either the target element 3 or 4.

Here's how the Twig to create a query like the above could look:

{# Create the base query #}
{% set query = craft.entries({ section: 'products' }) %}

{% set relatedTo = [] %}

{% set types = craft.app.request.getQueryParam('type')|split(',')|filter %}
{% if types %}
    {% set relatedTo = relatedTo|merge([{
        targetElement: craft.categories({ group: 'types', slug: types }).ids()
    }]) %}
{% endif %}

{% set sizes = craft.app.request.getQueryParam('size')|split(',')|filter %}
{% if sizes %}
    {% set relatedTo = relatedTo|merge([{
        targetElement: craft.categories({ group: 'sizes', slug: sizes }).ids()
    }]) %}
{% endif %}

{% if relatedTo|length > 1 %}
    {% set relatedTo = ['and']|merge(relatedTo) %}
{% endif %}

{% set entries = query.relatedTo(relatedTo ? relatedTo : null).all() %}

The above code should work for all the below use cases:

/products (returns all product entries)
/products?type=polo-shirt (returns all polo shirts)
/products?type=polo-shirt&size=small (returns all small polo shirts)
/products?type=polo-shirt,jeans&size=small (returns all small polo shirts and jeans)
/products?type=polo-shirt,jeans&size=small,medium (returns all small and medium polo shirts and jeans)

Note that the usage of ids() over all() in a few places (such as in the craft.categories queries to get the type and size categories) – this is a performance tweak (it's more effective to just pull the IDs than the entire model).

Also note that if you want to use pagination, just amend the final line to

{% paginate query.relatedTo(relatedTo ? relatedTo : null).limit(10) as pageInfo, pageEntries %}

Note: I originally typed out a completely different answer to this question, but after some helpful discussion with @Robin Schambach on Slack, we arrived on the above, IMO much better solution. Cheers Robin!


Craft Commerce: Duplicate Input for Address State?

This ended up being a css issue. In the CSS I had to create the following rule.

input[type="text"].hidden { display: none; }


Yes, use errorTemplatePrefix.

'errorTemplatePrefix' => "pages/",


Sure, http://buildwithcraft.com/docs/templating/paginate

{% paginate craft.entries.section('blog').limit(10) as entries %}
    First Page
    {% if paginate.prevUrl %}Previous Page{% endif %}

    {% for page, url in paginate.getPrevUrls(5) %}
        {{ page }}
    {% endfor %}

    {{ paginate.currentPage }}

    {% for page, url in paginate.getNextUrls(5) %}
        {{ page }}
    {% endfor %}

    {% if paginate.nextUrl %}Next Page{% endif %}
    Last Page

This outputs something along the lines of: First Page, Previous Page, (nearby page numbers), Next Page, Last Page


You could manage all your translations in one csv file. There's another Q/A about translation files, where @Bill Criswell explains how you can use csv files for translations. I added some variables to his script to make it well adaptable to multiple locales.

Set up your new csv file with a column for each locale. Then add the script to each of your lang.php files and configure $this_locale_column according to the file's locale.

<?php

$path = $_SERVER['DOCUMENT_ROOT'].'/../craft/translations/translations.csv';
$delimiter = ';';
$skip_rows = 1; //skip header rows
$primary_locale_column = 0; //set primary locale column
$this_locale_column = 1; //set secondary locale column for this `lang.php` file

$translations = array();
$translations_file = fopen($path, 'r');

if ($translations_file) {
    while(($translation = fgetcsv($translations_file, 1024, $delimiter)) !== FALSE) {
        if($skip_rows != 0) { $skip_rows--; continue; }
        $translations[$translation[$primary_locale_column]] = $translation[$this_locale_column];
    }
}

return $translations;


The conditional {% if craft.entries.section('projectEntries').order('postDate desc').one() %} basically just tests if the craft.entries.section query returns an entry or not. Obviously, that would evaluate to true on every entry template.

Instead, you probably want to test if the first entry returned by the above query is the same as the current entry. A good way to do that, is to compare the entry IDs:

{% set firstEntry = craft.entries.section('projectEntries').order('postDate desc').one() %}

{% if entry.id == firstEntry.id %}
    ...

To test for the last entry, you could do something like this (notice that the only difference from the above query is that the sort order is reversed):

{% set lastEntry = craft.entries.section('projectEntries').order('postDate asc').one() %}

{% if entry.id == lastEntry.id %}
    ...

If, however, you have access to the entry_prev and entry_next variables within the Twig block that renders the buttons, you can avoid extra database queries altogether by simply checking if those variables are null or not:

{% if not entry_prev %}
    {# No previous entry; the current entry must be the first #}
    ...
{% elseif not entry_next %}
    {# No next entry; the current entry must be the last #}
    ...
{% else %}
    {# The current entry is neither the first nor last #}
    ...
{% endif %}

If you can't use the entry_prev and entry_next variables, a more optimized way to do it than pulling the first and last entries would be to do something like the below – note the use of ids() instead of all(); this is an optimization due to it being cheaper to just pull the entry IDs instead of the full entry models:

{% set allEntryIds = craft.entries.section('projectEntries').order('postDate desc').ids() %}

{% set firstEntryId = allEntryIds|first %}
{% set lastEntryId = allEntryIds|last %}

{% if entry.id == firstEntryId %}
    {# The current entry is the first one #}
    ...
{% elseif entry.id == lastEntryId %}
    {# The current entry is the last one #}
    ...
{% else %}
    {# The current entry is neither the first nor the last #}
    ...
{% endif %}


console.groupCollapsed("Application Log"); - what is it?

This is something Craft only shows if your site is in devMode (http://buildwithcraft.com/help/dev-mode).

If you use Firebug or Chrome Developer Tools for instance, it shows you a performance and error log.

By disabling devMode, it disappears. Do this by setting 'devMode' => false into your craft/config/general.php.


Creating an active page within a channel

I would create a single template that is displayed when you visit /product and set entry to be the first entry in the Product channel that is live.

{% set entry = craft.entries.section('products').status('live').first() %}

All you need to do then is disabled all product entries apart from the product you want to display.

UPDATE: To avoid duplicate content or different content on the /product page you could redirect to the current product entry page /products/product-a using

{% redirect entry.url %}


How can I convert a date format from my plugin so it saves correctly?

After $entry->setContentFromPost($fieldsLocation); you should be able to add another line to explicitly set your calculated date.

$entry->setContent(array('fieldName' => $myDate));

Then just proceed with saving the entry as normal.


Twig generally doesn't like nested/un-nested blocks like this. A better way to deal with this would be to just set a variable; and since twig renders templates from the inside-out, any variables that you define in child-templates should be available to the parent.

So in 'main.twig':

<head>
    <meta property="og:image" content="{% if seoImage is defined %}{{ seoImage }}{% endif %}" />
</head>

And in your child-template:

{% extends "templates/main" %}

{# note: needs to be defined outside the 'for' loop to become available #}
{% set seoImage="" %}
{% for block in entry.articleBody %}
    {% if block.type == "articleImage" %}
        {% set seoImage = block.articleImage.first().getUrl() %}
    {% endif %}
{% endfor %}

You can still use blocks of course in addition to this technique, but generally best to keep them in the same nesting order.

On a side-note: I don't think you need the 'templates/' part of the extends statement (unless you have a 'templates' folder inside 'templates'). Normally you would just use {% extends "_main" %}. The underscore in the name also prevents the template from being loaded directly.


Using Sprout SEO, how do I use the seoDivider setting in templates?

The SEO Divider setting will be used if you select the "Append Site Name to all Titles" setting on the Basic SEO tab of your Default, and then override your title via code or a Meta Basic Field type.

For example, if the pipe character is selected as the divider:

Code Override Blog Post Name | Website Name

Meta Basic Field Override Title Value | Website Name


Cannot grant user group plugin permission without hasCpSection

The only point of those permissions is to determine whether the user has access to the plugins’ sections, so it would be pretty pointless to show the permissions for plugins that don’t have sections.

The confusion here is probably just in the wording of the permissions. “Access [Plugin]” isn’t very clear on which aspect of the plugin you’re granting access to. So maybe we should change that to “Access [Plugin]’s CP section” or something.

If you have a plugin that offers functionality that warrants user permissions, register your own custom user permissions using the registerUserPermissions hook, and verify that the user has those permissions using craft()->userSession->checkPermission().


So it seems that even although the Craft field is set to number it doesn't actually define a number.

I changed the field from a regular Craft table field to a Super Table field and my {{ donutData|json_encode }} corrects spits out an array of numbers.


The answer is to prepend a letter to the numerical key…
{% for entry in entries %}
    {% set eId   = "e#{entry.id}" %} {# interpolation* #}
    {% set value = entry.intro %}

    {% set myHash = myHash|merge({
        (eId) : { intro : value }
    }) %}
{% endfor %}

Now the hash stores the custom key as a string…
array(10) {
  ["e1234"]=>
  array(1) {
    ["intro"]=>
    string(13) "My intro text"
…

…which you can clean up as needed…
{% for key, properties in hash %}
    {% set key = key|replace('e', '') %}
    …
{% endfor %}

…or factor into lookups…
{% set testId    = 'e1234' %}
{% set testIntro = myHash[testId].intro %}
{# `testIntro`  == 'My intro text' #}

Apparently, it's a PHP thing.
*Interpolation is often preferable to concatenation <-- see item #4.


Redactor - doesn't generate unordered list

Redactor is perfectly capable of rendering an unordered list, so perhaps your question is a little unclear.
If you mean that there's no formatting button to format an unordered list, check that you're using an appropriate redactor config which allows the use of 'unorderedlist' in your field definition:

More instructions about how to configure Redactor in Craft can be found at https://github.com/craftcms/redactor


Currently the users/saveUser (and the deprecated users/setPassword) controller action doesn’t support Ajax requests, so there won’t really be an easy way to tell if it worked or not.

If you really want to update user passwords over Ajax, your best bet will be to write a plugin with its own custom controller action, which mimics the password-related stuff in UsersController::actionSaveUser(), but probably calls UsersService::changePassword() rather than saveUser() since you only care about updating the password. And have that controller respond with JSON if it’s an Ajax request, rather than assuming it’s not.

Take a look at EntriesController::actionSaveEntry() for an example of a controller action that does support Ajax.


The only feasible way of doing this without it being overwritten in each Craft update is by manipulating the elements using JavaScript. You can of course do this using your own module or plugin, but an easier approach would be to use the Control Panel JS plugin, which was created specifically to allow you to add JavaScript in the control panel.


Protect mutliple pages in a template folder

You pretty much nailed it.

If you have multiple pages that require an authenticated session, then have all of those pages extend a template that uses something like {% requireLogin %}.


Smart Map - How to search by a field in address?

It's more "filtering" than "searching", but take a look at this...

Filtering entries by subfield value

Set a filter parameter when creating your element criteria model...
{% set params = {
    filter: {
        city: 'Beverly Hills',
        state: 'CA'
    }
} %}

{% set meetings = craft.entries.address(params) %}


When the folks at Craft cut a release they can tag an update in one of several ways:

One-click Update
Manual Update

They can also tag their updates with a level of importance:

Normal Update
Critical Update

This helps Craft manage several scenarios that might occur that they need to account for during a release. When you see the "Manual Download" button it probably means that something changed in the code that could fail if an auto-update were performed or that they need to make sure everybody updates to that particular release before updating to any releases beyond that.

In this case, I believe the two things you have identified are from different releases. The Critical Update flag relates to release 2.6.2791 and makes the update badge in the Craft CP red, to indicate its importance. And the Manual Update flag relates to release 2.6.2922 where one of the bugs fixed related to the updater functionality itself, and they needed to trigger a manual download to make sure the files got updated properly.

A longer discussion of Critical Updates is available in this Straight Up Hangout:

Critical Updates and Craft CMS


Same shipping rule name in different methods not allowed?

Confirmed by Luke this was due to a bug to be fixed in the next release of Commerce.


I believe you'll want something like this...

{% if currentUser %}
    Logout
{% else %}
    Login
{% endif %}


Sprout Form Date/Time field not displaying

In the end I switched it to a default text field and used jQuery datepicker.


Paginate based on date-based starting points

Instead of using pagination you might want to look into setting up a dynamic route in the format "calendar/[year]/[month]". Adding 'year' and 'month' tags to your route will essentially pass those values as named variables to your template, which you can use to retrieve and display entries, as well as generate navigation to next/previous month's events. If you want the uri '/calendar' (without the 'year/month' uri segments) to link to the current months events you can test for the existence of the 'year' and 'month' variables, and if not defined, set the start month to the first day of the current month.

{% if year is defined and month is defined %}
    {% set startMonth = year ~ '-' ~ month ~ '-' ~ 1 %}
{% else %}
    {% set startMonth = now|date_modify("first day of this month") %}
{% endif %}
{% set nextMonth = startMonth|date_modify('+1 month')) %}
{% set previousMonth = startMonth|date_modify('-1 month')) %}

{% set entries = craft.entries.section('calendar').postDate('and', '>= ' ~ startMonth, '< ' ~ nextMonth %}

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

    next month
    previous month

If required, within any month you could also use a pagination tag if you needed to limit the number of events displayed on any one page to 15.

For additional examples see these answers, here and here.


If you are using the example templates, the dummy gateway should be enough to submit an order. Are you displaying any error flash message from the payment controller?

{{ craft.session.getFlash('notice') }}

{{ craft.session.getFlash('error') }}

The dummy gateway also expects a credit card that ends in an even number in order return a success:

https://craftcommerce.com/docs/payment-gateways#dummy-gateway


Is there a way to output the events that belong in a month after a specific date using the Calendar plugin by Solspace?

The calendar.month function is designed to only display complete months, so as long as you specify a date, it's going to show you events for that whole month (before and after).

What you're looking for is the calendar.events function:
https://solspace.com/craft/calendar/docs/calendar.events/

The code to display events starting from today plus 1 month (+30 days) would look something like this:

{% set events = craft.calendar.events({
   dateRangeStart: 'today',
   dateRangeEnd: '30 days'
}) %}

If you're looking to display events starting today but stop and the END of the current month, your code would look something like this:

{% set events = craft.calendar.events({
   dateRangeStart: 'today',
   dateRangeEnd: 'last day of +0 month'
}) %}


This seems to work:

{% set entries = craft.entries.section('not lakeDetails').search('title:' ~ query).order('score') %}


Output a default asset if one hasn't been specified

You can test if your first() method returns an asset model.
And depending on that have different image URLs, the (transformed) asset's one or the URL of your placholder image.

{% set image = block.mx_peoplePhoto.first() %}
{% set imageUrl = image ? image.url('500x500') : url('images/_static/placeholder.jpg') %}

<img src="{{ imageUrl }}">

You could also consider to get that placeholder image from a global set.


How to structure this multiple relation?

There could be corrupt data in your remote database. I tried to answer a similar case some weeks ago: "Entries related to Users", where the code was right, but Craft returned the wrong entries.

I'd check if it helps to clear the database and do a fresh import from you local environment.


Comparing current date to multiple entry matrix date fields

I think you've just got a logic problem.

{% if entryStart >= present and entryEnd <= present %}

The only way this will ever evaluate to true is if the entryStart and entryEnd DateTime fields have the exact same date and time (down to the second) that the present time is, which seems like a very small window.

You're essentially looking for an entry that lives in the future and in the past.


I was able to accomplish this by just adding both variables to my SuperSort tag. In essence, what I did was this:

{% set fruits = fruits | supersort('natsortas', '{count} {title}') %}

It seems to be working in my situation, but if there's a better way to do it, I'm open to suggestions.


Composer conflict when installing craftcms/plugin-installer

I had the same problem following that video, i assume the ReleaseCandidate upgrade differs from the beta upgrade. Following the instructions from the craftcms github repo worked for me. https://docs.craftcms.com/v3/upgrade.html


It was the single quotes around 'true' in the config file :)


Can plugin copy file into an asset source?

As you discovered, the way to go about this is with AssetsService::insertFileByLocalPath().

Not sure about the error you’re getting though. If you haven’t had any luck figuring that out, send your plugin over to support@buildwithcraft.com with instructions on how to reproduce, and we can look into it.


How to populate Category field form frontend form?

Couple things. First, I believe you need to add an extra set of brackets to the name attribute. The reason being that category fields (as well as all 'related' fieldTypes) store more than one element, even if as in this case there is only one category being assigned. Secondly you'll need to assign the category id as the value.

<select id="language" name="fields[language][]">
    {% for category in craft.categories.group('languages') %}
         <option value="{{ category.id }}">{{ category.title }}</option>
    {% endfor %}
</select>


Specify FolderId When Uploading a File on the Frontend

You can find a specific folder using the Assets service:
https://docs.craftcms.com/api/v3/craft-services-assets.html#public-methods
If you know all the necessary information when that template is parsed, the findFolder method might be useful but ensureFolderByFullPathAndVolume is probably more precise.
For example:
{{ hiddenInput( 'secret_folder_id',
    craft.app.assets.ensureFolderByFullPathAndVolume($volumePath, $assetVolume) ) }}


You're probably looking for something like:

craft()->request->getHostInfo().craft()->request->getRequestUri();

Which will return the host name with the schema it's using (http:// or https://) as well as any URI after the host including any querystring parameters.


sort by checkbox field with multiple options and by postDate desc

The equivalent SQL would be something like
SELECT * FROM players ORDER BY teamName IS NOT NULL DESC, postDate DESC;
but I'm not sure how that would translate in a simple element query. It'd be something like:
{% set players = craft.entries.section('players').orderBy('teamName IS NOT NULL DESC, postDate desc').all() %}


Running custom query save result to xml file

Sounds like a pretty simple custom Craft plugin.

You'd add a controller to your plugin and an action method and allow anonymous access to it.

Your method would run any queries you need and save the results to an XML file on the server somewhere.

Then setup cron to execution the action at whatever interval you want.

0 3 * * * curl -s -o /dev/null "http://mydomain.com/actions/myplugin/myaction"


"Failed to instantiate component or class" when calling Craft module

I came across the same issue. So how i solved it is to modify the modules array like this and now the module is loading:

return [
    'modules' => [
        'zip-assets-craft-3-module' => [
            'class' => \modules\zipassetscraft3module\ZipAssetsCraft3Module::class,
        ],
    ],
    'bootstrap' => ['zip-assets-craft-3-module'],
];


How to assign a URL to only one slide in a template using Matrix?

Try something like:

{% for block in entry.information %}
{% if block.type == "images" %}
    {% set image = block.image.first() %}
        {% if image %}
            {% if block.anchor |length %}

            {% else %}

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

So that only if the block.anchor field has something in it do you generate the link & the image. Otherwise, you just generate the image.


Creating and saving a GlobalSet element type in Craft 3

Answer:

So I looked in the craft core to see how the CP does it. Turns out we have to use this

$gs = new \craft\elements\GlobalSet();
$gs->name = "Meta";
$gs->handle = "meta";

Craft::$app->getGlobals()->saveSet($gs);

Hope this helps someone.

Craft core reference

https://github.com/craftcms/cms/blob/develop/src/controllers/GlobalsController.php#L55-L96


Plugin to report when site becomes unavailable

There's no plugin for that... it wouldn't quite make sense. If the site went down, the plugin would be down too.

Your best bet is to find a 3rd party service to monitor the site's uptime. There are several services which will alert (via text or email) if your site becomes unavailable. Here are a few examples...

Uptime Robot
New Relic
Pingdom


Possible to filter an entry based on property?

This should work below. Rather than querying all entries and looping through, just select the entries you need (ie. now) and limit them.

{% set upcomingEvents = craft.entries.section('events').eventDate('>= '~now).limit(2) %}
{% for event in upcomingEvents %}
    <!-- markup here -->
{% endfor %}


Applying changes from your project config files ... No site settings exist for section 20

If it's a new environment with your staging database, then run this on your new production environment:
./craft project-config/rebuild
This will force-dump the config into the project-config YAML files from scratch, and include any small changes that might have happened to make way for the new environment, including pesky caches.


Getting started with Order Adjuster plugin

To get an adjuster working, it's really all about consistent naming and making sure PHP can find the class.  Here are the main things to address:

Your adjuster should be defined in a file that matches it's classname

So in this case a folder off the main plugin folder:

 /craft/plugins/businesslogic/Adjusters/BusinessLogic_TaxRemover.php

Include the Adjuster class file.

You can do this (at least) two ways:

include or require the adjuster file in your main plugin class

e.g.

<?php
namespace Craft;

require_once('Adjusters/BusinessLogic_TaxRemover.php');

OR you can use Craft::import (which is probably the better way I guess?)

Craft::import('plugins.businesslogic.adjusters.BusinessLogic_TaxRemover');

** The Classname must match the filename **

So e.g. in this case

<?php

namespace Commerce\Adjusters;
use Craft\Commerce_LineItemModel;
use Craft\Commerce_OrderAdjustmentModel;
use Craft\Commerce_OrderModel;

class BusinessLogic_TaxRemover implements Commerce_AdjusterInterface {

   etc
}

You must also finally register your Adjuster with commerce

And again you must use the same classname (and be mindful of namespaces!)
So in this example:

public function commerce_registerOrderAdjusters(){
    return [
        new \Commerce\Adjusters\BusinessLogic_TaxRemover

    ];
}


Cache issues making site super slow in production but not in dev mode

This article (http://buildwithcraft.com/help/stuck-tasks) from Brad's comment was indeed the way to address this - and our logs did show this exceeding the php execution time. Thanks Brad!


SEOMatic: Get SEO Image from a Matrix Field

Since SEOmatic fields are parsed as object templates, you'll need to preface things like entry with object., e.g.:

{% set hero = object.entry.heroImages.one() %}{% set image = hero.image.one() %}{{ image.url }}

c.f.: https://github.com/nystudio107/craft-seomatic#content-seo-control-panel-fields

Note that you could also do this entirely in your Twig template, like this:

{% set hero = entry.heroImages.one() %}
{% set image = hero.image.one() %}
{% do seomatic.meta.seoImage(image.url) %}
{% do seomatic.meta.twitterImage(image.url) %}
{% do seomatic.meta.ogImage(image.url) %}


Who "owns" a Craft license is very loosely defined as far as Pixel & Tonic (the creators of Craft) is concerned.

A Craft purchase/edition is tied to the craft/config/license.key file that is in place at the time a purchase is made and wherever that file goes, the purchase/edition will follow.

In addition to that, a license.key file can only ever be tied to one public domain at a time.

As long as you give your client that license.key file and don't use it for other clients or projects, they "own" it.

How the license gets paid for is more up to you and your client.  i.e. either you purchase it and bill the client as a line-item on an invoice or have them purchase it directly.

Some relevant reading:

https://craftcms.com/support/license-key-info

https://craftcms.com/support/license-enforcement


Need Swift Mailer to send emails as UTF-8

Completely untested, but try setting this in your public index.php file right before Craft executes:

\Swift_Preferences::getInstance()->setCharset('UTF-8');

Based on https://swiftmailer.symfony.com/docs/messages.html#setting-the-character-set


I did end up opening a support ticket with Craft- they immediately suggested that this could be caused by a firewall. To which I scoffed! But after talking with some other folks in the office, this seems to be the case.

Unfortunately we never found a firewall solution to this problem. What did work was to assign a static IP to my computer that bypasses the http-proxy packet filter.

So yeah. Firewall. Dang.


How to include a section name in the page title?

{{ entry.section }} - {{ entry.title }}

Here are a list of properties you can get from the Entry model:

https://craftcms.com/docs/templating/entrymodel

So you could do

{% set title = "#{entry.section} | #{entry.title}" %}


Have SEOMatic render a custom SEOMatic field

So the default global settings for SEOmatic should definitely be applied to pages that don't have corresponding entries in the CMS. That's what the global defaults do.

By far the easiest way to do what you want is just to create a Single that corresponds to these otherwise non-managed pages, and then you can set up whatever you like in the corresponding Content SEO settings.

If you don't want to do that, you can set everything yourself via the Twig API:

https://nystudio107.com/docs/seomatic/Using.html#seomatic-variables

You could try doing something like:

{% do seomatic.meta.setAttributes(myCustomSeoMetaField.metaGlobalVars)
%}

As per: https://nystudio107.com/docs/seomatic/Fields.html#template-access

But in general, I think this is a rougher work-around than just creating a Single for the previously non-content managed pages.

To be clear:

  PS the reason I want to do it this way is partly because the Global/default SEOMatic settings didn't seem to be coming through on a non-entry, so I was hoping using some sort of default hook will take care of this also.

This should not happen. You absolutely should get the default SEO settings on every page, so if this isn't happening for you, something deeper is wrong.


Something like this should work:

{% set sections = [] %}

{% set sections = sections|merge([craft.sections.getSectionById(1)])
{% set sections = sections|merge([craft.sections.getSectionById(2)])
{% set sections = sections|merge([craft.sections.getSectionById(3)])

{% for section in sections %}
    ...
{% endfor %}


You don't actually need to look at the URL segments, because Craft automatically populates your template with a category variable whenever it matches the current URL to a category's URL. All you need to do, is to make sure that your category URLs point to the correct template, and to account for that template being rendered both with a category variable and without (i.e. for the default news index listing).

First, you'll need to make sure that the URL format for your category group is correct – you should probably use something like news/{slug} or perhaps news/categories/{slug}. Also, set the "Category template" to your news index template, e.g. news or whatever template path you're actually using for the news index.

Then, you can filter your entries like the following, using the relatedTo parameter:

{% set category = category ?? null %}
{% paginate craft.entries.section('news').featured('not 1').relatedTo(category).limit(6) as pageInfo, pageEntries %}

...

One gotcha to note is that whenever you pass a NULL value to the relatedTo() parameter (which will happen whenever the category variable is empty), Craft will ignore the parameter and return all entries – which works in this case, as the same template should also double as your news index.


What is the appropriate way to query and Hard Delete existing Soft Deleted Elements for a Custom Element?

I figured this while posting so I thought I'd just add it here anyway for others to reference.

To retrieve a Soft Deleted Element using the getElementById method you can pass the fourth argument to the getElementById method and define $criteria setting trashed to true, which will include Soft Deleted items in your results:

$element = Craft::$app->elements->getElementById($elementInfo['elementId'], MyCustomElement::class, $elementInfo['siteId'], [
    'trashed' => true
]);


I know a lot of 3D programs are going to use different file formats. And the viewers tend to vary quite a bit. What are you using?  If you can export to obj format, three.js seems popular.

There's also services that do the heavy lifting of embedding as well. (Kind of like Vimeo for models). Just did a little bit of searching, SketchFab seems interesting and they also offer a free plan. They accept a bunch of file formats plus an API which you could tap in Craft.

They also do oEmbeds so you could use something like Embed Assets to hook into it.


Add an add entry button to my Plugin in Craft CP

I believe what you need is the elementSelect field type which Craft bundles with the CMS. You can find the template of this field in craft/app/templates/_includes/elementSelect.html

Here's a quick example that will get you started:

{{ forms.elementSelectField({
    label: 'Select An Entry'|t,
    instructions: 'Select...'|t,
    id: 'entry',
    name: 'entry',
    elementType: craft.elements.getElementType("Entry"),
    source: '',
    criteria: '',
    sourceElementId: '',
    elements: '',
    storageKey: '',
    viewMode: 'list',
    limit: 1
 }) }}


Is there a way to format the Asset Size variable to Mb, Kb, etc.?

This should do it:

{% set bytes = asset.size %}
{% set kiloBytes = (bytes / 1024)|round(2) %}
{% set megaBytes = (kiloBytes / 1024)|round(2) %}

bytes = {{ bytes }}
kiloBytes = {{ kiloBytes }}
megaBytes = {{ megaBytes }}

You can look at Twig's number_format filter if you want to get fancy with how to display the numbers.


You'll want to go through Craft's service layer to get things like that.

There is a UserGroupsService, which has all sorts of handy methods for retrieving UserGroups like getGroupById() and getGroupByHandle().

You can invoke these from your plugin like:

$userGroup = craft()->usergroups->getGroupById(3);
$groupName = $userGroup->name;

Note that these will return a UserGroupModel populated with your UserGroup information.


No software is perfect. Like any other well-managed software project, Craft CMS is regularly updated with new features, improvements and bug fixes.

Occasionally, the changes will relate to a specific security issue that has been discovered in the software.

By not updating, you are missing out on the new features, improvements and bug fixes that make Craft CMS better.

If you don't update when a new security issue is patched, then you are leaving your site at risk of exploitation of the security vulnerability. Depending on the nature of the specific vulnerability, that could mean a threat to your site, your business, the web server that your site is running on or all of them.

Note that this applies to all software, not just Craft CMS.

The Craft CMS changelog is a good resource to see what changes are included in each update.


Not actually possible. That icon key is not being used anywhere – just a remnant from a past feature idea that didn’t make it into Craft 2.5. (I just removed it for the next release.)


Get PDF file from Assets Folder - Element API

You have to check if your matrix element has a block or not with the code $block->downloadablePdf[0]->url you'll access the first element in your matrix but when there is no it will throw an error.

'downloadablePDF' => $block->downloadablePdf[0]? $block->downloadablePdf[0]->getUlr() : ''

will check if there is an asset and return the url or an empty string if there is no asset


How to implement "cookie consent message" to visitors of our website using Craft 3

Just search for "Cookie" in the plugin store. There are several free ones along with some paid. I have used the Cookie Consent Banner on a couple sites.


Is it possible to create a plugin using Python in Craft 2?

I think you're going to have a bad time if you attempt to do this. Probably a better way would be to use PHPPresentation to read in the .pptx files.

Integration is certainly possible between server-side languages, but you're going to have to jump through a good deal of hoops that you could more easily just avoid by writing your plugin in PHP.


Use sidebar nav icons in modules and plugins

You were almost there with it. You need to specify a path to an SVG. It can be one of the ones that exists within Craft's icon directory.

So your nav item would look like this:

Event::on(
    Cp::class,
    Cp::EVENT_REGISTER_CP_NAV_ITEMS,
    function(RegisterCpNavItemsEvent $event) {
        $event->navItems[] = [
            'url' => 'contact-enquiries',
            'label' => 'Contact Enquiries',
            'icon' => '@app/icons/envelope.svg',
        ];
    }
);

And this is how it will show in the CP nav:


Getting properties out from the Craft text object

This Object has a __toString function that executes return $this->content;.
If you are in a template just do

{{ object }}

You can call the function getParsedContent as well

{{ object.getParsedContent() }}

In PHP

$text = $object->getParsedContent();


How can I know the discounts available to a product before adding it to the cart?

You currently can not know if a product matches a discount until it is added to the cart and the discount engine does the checks based on the full conditions of the discount. Many conditions of which are directly related to the product being in the cart. For example a minimum order qty.

But if you want to return a possible list of discounts to show the custom of which the product MAY be eligible before adding to the cart then you can do something like this:

{% for discount in craft.commerce.discounts %}
  Possible Discounts:

  {% if product.id in discount.productIds or product.typeId in discount.productTypeIds %}
    {{discount.description}}

  {% endif%}
{% endfor %}

This only checks the product and it's product type is explicitly listed in the discount, but you can add additional conditions if you wished.

It is recommended the discount description has a readable sentance for how this discount could be applied. For example:

  Buy 2 or more sneakers and get 75% off.


Replacement for deprecated AssetsService

Most of the Assets related classes in Craft 2 have been deprecated because they've been completely re-written/refactored/removed for the upcoming Craft 3.

So if you're looking for a Craft 2 replacement, there isn't one... the replacements are in Craft 3.


I see this question as two parts: information architecture and templating.
If you're used to something like WordPress where the template has a one-to-one relationship with how the template gets data and how information is routed, ignore everything you've learned.
Templating
Let's get the requirement of reusing templates out of the way first. Twig, Craft's templating language,  lets your reuse templates quite easily.
Not only can you use reuse templates from any page inside Craft, you can also extend templates from other templates.
Craft then lets you define which template is going to be used for each section. You could just set it to a single one and be done with it if your content doesn't change that much from section to section. A single Matrix field could pull off quite a bit across the entire site.  Speaking of...
Matrix
Matrix fields can be used for "site builder" like functionality. Matrix lets you define block types (eg Pullquote, Featured Image with Caption, etc) and then by mixing and matching the blocks, you can "build up" a page. The blocks can also be reordered. That gives authors a lot of flexibility in how they layout the pages.
Entry Types
Entry types define what content Sections contain but unless you define the same Entry Types across multiple Sections, they're not "global" like Matrix fields would be.
Entry Types are useful if you need to define content (and layout) requirements for entries in the same section. If you curate a blog for example, you might have a "Link" Entry Type that links to other entries or even other blogs. Then you might have a "Blog Article" Entry Type for "regular" content.
In your templates, you have the ability to check which Entry Type the entry happens to be and have your template format it how it should look. The Happy Lager does this inside the News section.
Information Architecture
In my experience, there aren't any hard and fast rules for using Matrix and Entry types, it really depends on your content and requirements. You could probably pull off what you're asking for with either.

If your templates are "designed", meaning the products are always going to live in a certain spot inside a template, then you can probably use a relational field to define the relationship.

If you want your authors to be able to define multiple elements on a page and then pull in the products from anywhere, Matrix is going to be your weapon of choice

Mijingo just introduced a course you might find useful on the subject as well.


How to place assets in plain text fields?

Matrix fields in Craft are much more powerful than EE. In EE each Matrix row has a single set of fields available to it (a limitation of using a table-based UI). But in Craft you can set up multiple “block types” for a single Matrix field, each with a different set of fields.

So you can manage your text and assets all with a single Matrix field, with Text and Image block types. When an author wants to “insert” an image in the text, they can just click the button to create a new Image block; then continue writing more text by clicking the button to create a new Text block.

In your templates, you loop through each of the blocks, and output different HTML depending on the block type:

{# Load the blocks, eager-loaded with their image assets #}
{% set blocks = entry.yourMatrixFieldHandle
    .with(['yourAssetsFieldHandle'])
    .all() %}

{# Loop through them all #}
{% for block in blocks %}

    {# Alter the HTML output depending on their block type #}
    {% switch block.type.handle %}

        {% case 'text' %}

            {{ block.yourTextFieldHandle }}

        {% case 'image' %}

            {# Make sure that an asset is actually selected #}
            {% if block.yourAssetsFieldHandle|length %}

                {% set image = block.yourAssetsFieldHandle[0] %}

                {# Set the positioning class #}
                {% switch block.yourFloatFieldHandle %}
                    {% case 'left' %}
                        {% set class = 'float-left' %}
                    {% case 'right' %}
                        {% set class = 'float-right' %}
                    {% case 'center' %}
                        {% set class = 'center' %}
                    {% default %}
                        {% set class = '' %}
                {% endswitch %}

                {# Get the transformed image URL based on the chosen width and height #}
                {% set imgUrl = image.getUrl({
                    width: block.yourWidthFieldHandle,
                    height: block.yourHeightFieldHandle
                }) %}

            {% endif %}

    {% endswitch %}

{% endfor %}

Replace all the your____FieldHandle references with your actual field handles.

You also may wish to store image alt text either on the block or image, rather than just using the entry title. In that case replace the entry.title references with block.yourTitleFieldHandle or image.yourTitleFieldHandle.

(To create a custom field on your images themselves, create a new Text field in Settings → Fields called “Alt Text”, and then go to Settings → Assets → [your volume name], and add the Alt Text field to the volume’s field layout. You will then be able to access the field by double-clicking on your assets, either from the main Assets page or from within your Matrix field after you’ve selected an image.)


How to list different product types separately in order summary?

You'll need to query the Purchasable in order to sort by Type.

Hope this helps. Let me know if you find a better way.

Products

{% for item in order.lineItems %}
    {% if item.purchasable.product.getType().name == 'Products' %}
        {% set variant = item.purchasable %}
        {% set product = variant.product %}

{{ product.title }} - ({{ item.qty }})

    {% endif %}
{% endfor %}

Services

{% for item in order.lineItems %}
    {% if item.purchasable.product.getType().name == 'Services' %}
        {% set variant = item.purchasable %}
        {% set product = variant.product %}

{{ product.title }} - ({{ item.qty }})

    {% endif %}
{% endfor %}

Others

{% for item in order.lineItems %}
    {% if item.purchasable.product.getType().name not in ['Products','Services'] %}
        {% set variant = item.purchasable %}
        {% set product = variant.product %}

{{ product.title }} - ({{ item.qty }})

    {% endif %}
{% endfor %}


The "Thing" section could be set as a structure if you're planning of having hierarchy, if not, a channel would suffice. You would then create common fields that pertain to all "Things" and add them to all your entry types.

"Types" would be your entry types that would have different fields that are unique to the "Type" of "Thing".

Thing (Section - Structure/Channel)

Name (Title)
Primary Image (Asset)
Description (Rich Text)
Types (Entry Types)

Product (Entry Type)

Category (Categories)
Features (Matrix Field)

Name (Plain Text)
Image (Asset)
Description (Rich Text)

With this content model you'd be able to extrapolate quite a robust PIM system.


If Entry is related to Category-A, then print xyz

All you need to do is this in the product for Loop

{% if product.category.first.slug == 'brandx' %}
    Brand X
{% endif %}

Or Shorthand

{{ product.category.first.slug == 'brandx' ? 'Brand X' }}

Not tested but thats the gist of it.

--Edited


This is really difficult to provide a proper answer for in its current form, so I'll give some general advice when troubleshooting things like this.

Try to limit the complexity of the Twig code building the query.  It might help to break it up into multiple, smaller queries instead of executing everything as one monolithic query.
Don't do this in Twig. Break out into a plugin/PHP using a template hook and grab only the data you need using query builder. Again, it might help to break things up into multiple, smaller queries even from PHP.
Enable devMode and find the resulting SQL that is generated.  Use standard MySQL slow query debugging techniques to see where the bottleneck is and optimize from that information.
Finally, you can try to throw more resources at your server and brute force your way though it.


Twig Templating If statement (Unexpected tag name error)

It seems like you want to set offset to false after your first section.

To do this correctly you would need to use set like this:

{% set offset = false %}

Checkout the documentation to set a variable


Allow user to set timezone from within Craft when entering a time in a date/time field

I solved that by adding a dropdown field to user profiles where I allowed users to select timezone and then in custom module set the selected timezone like this:
class SiteModule extends Module
{
   public function __construct($id, $parent = null, array $config = [])
   {
       // Set correct Timezone
       $currentUser = Craft::$app->getUser();
       if ($currentUser) {
           $user = $currentUser->getIdentity();
           $timezone = null;
           if ($user->userTimeZone->value) $timezone = $user->userTimeZone->value;
           if ($timezone) {
               Craft::$app->setTimeZone($timezone);
           }
       }

       ...

If user is not logged in or does not have a timezone set Craft will use the system timezone for those users.
Timezone dropdown values are in the form 'America/Chicago'.


You'll want to make use of the level property of your entry...

{% if entry.level == 1 %}
    <!-- Top Level Links -->
{% else %}
    <!-- Child Links -->
{% endif %}


DateTime::__construct(): Failed to parse time string

You're getting that error because Do., 07 Sep. 2017 10:32:05 isn't in a valid PHP Date/Time format when you pass it into the |date filter.

Changing it to 07 Sep. 2017 10:32:05 should work.


One option is to use the onBeforeSaveTag event to capture the tag before it is saved. You can then use PHP's strtolower to normalize all of your tags.

In a plugin's main file, your init() function should have something like this:

public function init()
{
    craft()->on('tags.onBeforeSaveTag', function(Event $event) {
        $event->params['tag']->title = strtolower($event->params['tag']->title);
    });

}


Template for submit via ajax to Guest Entries plugin

There are some problems with your JavaScript that I expect is the cause of your issue.

From your code I'm assuming you're using jQuery Validate to validate the form before submission. Your first issue is the line

event.preventDefault();

within the submitHandler() method – jQuery Validate will actually prevent the default form submission for you, so this line is redundant. Also, there is no variable called event, so that's going to cause trouble.

The second issue is that you're using the wrong syntax for the $.ajax() method. Considering your current code, I believe you want to use the $.post() method instead.

Finally, you're serializing the wrong object – $(this).serialize() should actually read $(form).serialize().

With the above issues fixed, your code should look like this:

$(document).ready(function () {

    $('form#brick').validate({

        ignore: ":hidden",

        rules: {
            "fields[firstName]": {
                required: true,
            },
            "fields[lastName]": {
                required: true
            },
            "fields[email]": {
                required: true,
                email: true
            }
        },

        messages: {
            "fields[email]": "Email is required"
        },

        submitHandler: function (form) {

            var data = $(form).serialize();

            $.post('/', data, function (response) {
                if (response && response.success) {
                    $('#thanks').fadeIn();
                    $('#brick').fadeOut();
                } else {
                    alert('An error occurred. Please try again.');
                }
            });

        }

    });

});

Finally, for some pointers on how you could handle errors within the response payload, see this thread.


If I create a folder assets at that location it works. I don't know what this asset folder is about.


Plugin to maintain data integrity between related entries?

I think you've pretty much nailed the options.

1) Seems completely doable and relatively easy as of Craft 2.3 just like you described.

2) Is more difficult. You could go a custom field type route where you have settings defined which define which entry fields the cascading entry deletions occur on.  You could also probably cram your own modal/dialog choices into that event to present to the user for specific cascading deletion options (which is what I think you're also describing).

It probably be a lot easier if you didn't need to be concerned about which fields it happened to and you could go scorched earth and just recursively delete all reverse related entries regardless of the field or depth.  But I doubt that's the desired behavior in most circumstances.

I'd also be curious to see what an example of the use-case for this would be. My limited imagination is having a hard time coming up with something.


What is the checkbox for when editing Matrix fields?

The checkboxes can be used to select multiple matrix blocks at once to apply any action to the selected group. For example, you can select three different blocks and collapse, disable, or delete all of them using the settings gear on any of the selected blocks. You can also select multiple blocks are drag them all at the same time to re-order.


Checking if user authored an entry in another channel while in loop, N+1 problem

There's one bit missing in the constrains you explain above, do users end up with 1 entry only per channel so a total of 2 posts max?

If so, we know that:

each users can have a max of 2 posts
a user cannot post in B is they haven't completed their post in A

So assuming this first condition is also true (2 entries/user) you could just loop through users post count looking for those with less than 2 posts and they would automatically be the users who haven't posted in B..? Just a shot in the dark :)


If you FTP up the entire vendor folder, all of the same libraries should be available. Make sure it is properly installed locally, first.


Sorting across blocks (to get prev/next links)

You can get all of the works entries related to your contents Matrix field like so:

{% set works = craft.entries({
    relatedTo: { sourceElement: issue, field: 'contents.works' }
}) %}

They will most likely be out of order though. We can control that with the order parameter.

If you enable Dev Mode and look at the resulting SQL query in your browser console, you will see these two tables getting joined into it:

LEFT JOIN `craft_relations` `sources1` ON (sources1.targetId = elements.id)
LEFT JOIN `craft_matrixblocks` `target_matrixblocks1` ON target_matrixblocks1.id = sources1.sourceId

So we can pass in an order param that tells MySQL to order the entries by the block order first and their relation order second:

{% set works = craft.entries({
    relatedTo: { sourceElement: issue, field: 'contents.works' },
    order: 'target_matrixblocks1.sortOrder, sources1.sortOrder'
}) %}

Now you’ve got all of the Works entries in the proper order, and you can pass them into getPrev() and getNext():

{% set prevEntry = entry.getPrev(works) %}
{% set nextEntry = entry.getNext(works) %}


Q: Call to member function on null - Freeform (Solspace)

Please read the article handling errors gracefully in Craft  it will explain to code defensively and what to do in those scenarios. Your $user variable is null and you can't execute functions on null variables


Possible to paginate product variants in Craft Commerce 2?

product.variants returns the variants for the product as an array only. It is not like a element relationship field which returns an element query.

If you want to use a element query of variants for a particular product you can do:

craft.variants.product(product).all


Based on this clever tweet, you can do this:

{% set allEntriesByDay = craft
  .entries()
  .section('stories')
  .orderBy('postDate DESC')
  .with(['categories'])
  .all() | group(e => e.postDate|date('long')) %}

{% set dataProvider = create({
  'class': 'yii\\data\\ArrayDataProvider',
  'allModels': allEntriesByDay,
  'pagination': {'pageSize': 3}}) %} {# Set the days per page here #}

{% set results = dataProvider.getModels() %}

{% set currentPage = dataProvider.getPagination().getPage() + 1 %}
{% set totalPages = dataProvider.getPagination().getPageCount() %}

{% if currentPage > 1 %}
  {% set prevPage = currentPage - 1 %}
{% endif %}
{% if currentPage < totalPages %}
  {% set nextPage = currentPage + 1 %}
{% endif %}

{% if results | length %}
  {% for day, entriesInDay in results %}

{{ day }}

    {% for entry in entriesInDay %}
      {{ entry.title }}

    {% endfor %}
  {% endfor %}

  {% if prevPage is defined %}
    < Previous page
  {% endif %}

  {% if nextPage is defined %}
     - Next page >
  {% endif %}

{% endif %}


compiled_templates folder using up inodes on Ubuntu 14.04 Server

How many files are in the compiled_templates directory? There should be a 1:1 correlation between the number of actual templates you have, and the number of cached .php compiled templates in the compiled_templatesfolder.

It shouldn't have anything to do with 404 errors, etc.

I've never seen nor heard of the situation that you've described.


I assume you're talking about getting the email address of the currently logged in user?  That's what EntryModel's authorId property will get set to, if one isn't explicitly supplied.

If so, you can do that with:

$email = craft()->userSession->getUser()->email;

If you want to get the email address of the user that is the author of the entry, then you can do:

$email = $entry->getAuthor()->email;


Loop through Matrix Block fields within a Switch Case and retain HTML structure

You'll want to implement something like this:

{% for block in entry.menuBuilder %}

  {% set type = block.type.handle %}
  {% set isFirstConsecutiveBlockOfType = (loop.first or type != block.getPrev().type.handle) %}
  {% set isLastConsecutiveBlockOfType = (loop.last or type != block.getNext().type.handle) %}

  {% switch block.type %}
  {% case 'menuItem' %}

    {% if isFirstConsecutiveBlockOfType %}

    {% endif %}

{{ block.dishName }}

{{ block.dishDescription }}

{{ block.dishPrice }}

    {% if isLastConsecutiveBlockOfType %}

    {% endif %}

  {% case 'subHeading' %}

{{ block.heading }}

  {% endswitch %}
{% endfor %}

Basically, for each block we're checking if it is the first or last item in the loop, or if that block's type doesn't match the previous or next block's type. This will let us know if the block we're dealing with is the first or the last in a series of menuItem blocks. Then in the switch/case we can use our new variables to conditionally include any wrapping html.


Display parent category with nested child categories and related entries

This won't be super efficient if you have a loads of teams/people as it will run an entry query per subteam (and it won't check for empty teams either) but it should get you started.
{% set categories = craft
    .categories()
    .group('team')
    .level(1)
    .with('children')
    .all() %}

{% for category in categories %}

{{ category.title }}

    {% for child in category.children %}

            {{ child.title }}

        {% for entry in craft.entries.section('team').relatedTo(child).all() %}

{{entry.title}}

{{entry.positionTitle}}

{{entry.emailAddress}}

Tel: {{entry.telephoneNumber}}

Mob: {{entry.mobileNumber}}

        {% endfor %}
    {% endfor %}

{% endfor %}


Query two sections filtered by different custom fields, then order them

There's this super useful SuperSort plugin that would make this possible.

{% set sortAsTemplate = '{{ object.section == "Exhibitions" ? object.startDate|date("U") : object.date|date("U") }}' %}
{% set sortedOccurrences = allOccurrences|supersort('sortAs', sortAsTemplate) %}


Craft commerce 3 - Module - Lineitem - Get usergroup

Remembering a) that not all customers are users and b) that a user can be in one, or more, groups.....then something like this can be used to check if a user is in a particular group:
            $order = $lineItem->getOrder();
            $user = Craft::$app->users->getUserByUsernameOrEmail($order->email);
            if ($user){
                foreach ($user->getGroups() as $group) {
                    if ($group->id == someParticularValue){
                        //do stuff
                    }
                }
            }


Can we hide version number in control panel for certain user groups?

You would need to write a plugin that hides it with Javascript. We don’t have any plans to make it customizable.


Custom module controller getView()->renderTemplate() path not working

The correct path would be

return Craft::$app->getView()->renderTemplate('subscribing-module/templates/default',['mypost' => $request]);

And the file lives in modules/subscribingmodule/src/templates/default/index.twig


There is actually quite a bit of documentation on templating for various field types. Go to the Fields section of the online docs and then select the field you are interested in, e.g. you will find a very comprehensive templating guide for assets here


Can craft omit default locales from generated paths?

In your config file you will want to define the locales such that en points to the root directory.

'siteUrl' => array(
    'en' => 'http://craft.dev/',
    'cy' => 'http://craft.dev/cy/'
 ),

And your public html folder should not include an 'en' folder:

/craft
/html
    /cy
        /.htaccess
        /index.php
    /.htaccess
    /index.php


Craft Commerce Categories and Product Types

Product Types are really for the content of the fields and field layout of each product plus basic options for things like tax/shipping category defaults.

For full categorization in menus and site structure, we recommend putting a category field on all products.

For example you might have a category field names 'department' which you put all products into.

You then could show all products related to that category: https://craftcms.com/support/entries-related-to-category

Let me know if you need more guidance in the comments.


Eager loading on entry not reducing queries

I don't think eager loading will help in this case because you're trying to eager load fields with only a single relationship (asset). It's not the n+1 query problem eager loading is meant to solve.

If you had an asset field with multiple assets selected, you would see some benefit. But even then, if there are only a few assets, the small penalty of eager loading might not outweigh the small cost of queries for a few assets.

Bigger gains would come from nested relationships. For example, a set of related entries each with an asset for a thumbnail image.

{% do craft.app.elements.eagerLoadElements(
    className(entry),
    [entry],
    ['entriesField.image1']
) %}

{% for item in entry.entriesField %}
    {% set image = item.image1[0] ?? null %}
    {% if image %}
        {{ image.url }}
    {% endif %}
{% endfor %}

Also, it might be worth noting that in your testing, it matters what data you actually use.

In my test, this produced 19 queries:

{% set asset = entry.headerImage.one() %}
{{ asset.title }}

But this produced 23 queries:

{% set asset = entry.headerImage.one() %}
{{ asset.url }}


Maybe you should take a look what the function createField does

Creates a field with a given config.
return    craft\base\FieldInterface  The field

It only creates a PHP object but does not save the field at all.
Craft::$app->getFields()->saveField($field);

is what you want
This is what the FieldsController does to store a new field
public function actionSaveField()
{
    $this->requirePostRequest();

    $fieldsService = Craft::$app->getFields();
    $request = Craft::$app->getRequest();
    $type = $request->getRequiredBodyParam('type');

    $field = $fieldsService->createField([
        'type' => $type,
        'id' => $request->getBodyParam('fieldId'),
        'groupId' => $request->getRequiredBodyParam('group'),
        'name' => $request->getBodyParam('name'),
        'handle' => $request->getBodyParam('handle'),
        'instructions' => $request->getBodyParam('instructions'),
        'translationMethod' => $request->getBodyParam('translationMethod', Field::TRANSLATION_METHOD_NONE),
        'translationKeyFormat' => $request->getBodyParam('translationKeyFormat'),
        'settings' => $request->getBodyParam('types.'.$type),
    ]);

    if (!$fieldsService->saveField($field)) {
        Craft::$app->getSession()->setError(Craft::t('app', 'Couldn’t save field.'));

        // Send the field back to the template
        Craft::$app->getUrlManager()->setRouteParams([
            'field' => $field
        ]);

        return null;
    }

    Craft::$app->getSession()->setNotice(Craft::t('app', 'Field saved.'));

    return $this->redirectToPostedUrl($field);
}


Detailed instructions are now provided here: https://docs.craftcms.com/v3/upgrade.html


As far as I know you should manually set the progress value. The task can't determine the progress by itself, unless you are returning/polling this data.

An example of how we use it, for sending activation mails to multiple users;

public function execute($queue)
{
    // creation date of user
    $days = ($this->data['creationDate']) ? $this->data['creationDate'] : 7;

    // get pending users
    $dateFilter = (new \DateTime( $days . ' days ago'))->format(\DateTime::ATOM);
    $users = \craft\elements\User::find()->status('pending')->dateCreated(" < {$dateFilter}")->all();

    // loop
    $totalUsers = count($users);
    $currentUser = 0;

    foreach($users as $user) {
        // send mail
        $result = $this->sendReminderMail($user);

        // update progress
        $this->setProgress($queue, $currentUser++ / $totalUsers);
    }
}

setProgress is used to update the progress, which will be visible in the CP.


Most likely you have AWS policy issue. Never seen the problem you've described
Craft still will save images copy locally to improve speed. You can disable it using maxCachedCloudImageSize config and set it to 0.


Loop through entry titles in a select field

The issue is you don't have a variable named input. I changed the code a little by included a variable named value. To make sure the proper option is selected you would need to pass back to the template a url param name with the currently selected option value.  If there is a param and it has a value it will add that value to the variable value if not value will be blank.

<label>Position Applying For</label>
{% set value = craft.request.getParam("name")?? "" %}
<select name="{{ positionApplyingFor.handle }}">
    {% for entry in craft.entries.section('careers') %}
        <option value="{{ entry.title }}" {% if value == entry.title %}selected{% endif %}>
            {{ entry.title }}
        </option>
    {% endfor %}
</select>


How do you prevent white space from being removed after line breaks within a Rich Text Field?

Unfortunately you can't really configure how Redactor formats it's input. Given this I think your current solution is the most effective.

That said, you could try this alternative style for your <br> tags when hiding:

br.hide-for-small {
    content: '';
    display: inline-block;
    width: 1ch;
}

This will collapse the line break with an added space. It'll only work on Safari and Chrome though. That might be good enough since most mobile users are using Webkit-based browsers.


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

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


How do you output the value of a checkbox item?

Ok, just figured it out. Apparently, when I changed the value of the fields in the settings I had to re-save all entries that used that field. And not just re-save them, but reset the value in the field as well, because it had lost it's checked value when I opened the entry up to edit it.

I see now the warning in the field settings I had previously overlooked, "Changing this may result in data loss."


A pure ghetto method would be to just go into the pdf template and remove the "paid" markup.

I can't remember off hand, but I think it is just a div. Inspect the element to find the hook (id, class). Then either comment out the css rules or remove that element.

EDIT

It looks like this is the file you need to modify:

/craft/templates/commerce/customer/order.html


How to identify the recurring payments that happen after the initial subs creation payment the in Commerce Subs

Listen to the invoice.payment_succeeded webhook and check the billing_reason for subscription_cycle. Full answer here: https://stackoverflow.com/a/54165193/1215040

use craft\commerce\stripe\base\Gateway as StripeGateway;
use craft\commerce\stripe\events\ReceiveWebhookEvent;
use yii\base\Event;

Event::on(
    StripeGateway::class,
    StripeGateway::EVENT_RECEIVE_WEBHOOK,
    function(ReceiveWebhookEvent $e) {

        if ($e->webhookData['type'] == 'invoice.payment_succeeded') {
            $invoice = $e->webhookData['data']['object'];
            if ($invoice['billing_reason'] == 'subscription_cycle') {
                // It's not the first payment!
            }
            if ($invoice['billing_reason'] == 'subscription_create') {
                // It's the first payment!
            }
        }
    }
);


Checking the link type from a LinkIt field returns the whole path

Please have a look at the new docs for the plugin version for craft 3: https://github.com/fruitstudios/craft-linkit/blob/master/README.md#using-linkit

Instead of {{ entry.linkItField.type }} you should use {{ entry.linkItField.typeHandle }}


Using Craft CMS with Foundation 6 (for Sites)

Craft is completely "BYO HTML", so there is no magic in making Foundation work with Craft, unlike lesser CMSes that force their own HTML on you.

Just add your stylesheet links and script tags to your main base HTML wrapper and have fun building!


You need to use the Update Asset Indexes tool in Settings in the control panel:

  Whenever there are files within your asset source that were not added directly by Craft (e.g. via FTP), you will need to tell Craft to go and look for them. You can do that from the “Update Asset Indexes” tool within Settings.


I think setNotice is what you're after;

Craft::$app->getSession()->setNotice('Your message');


Craft/Yii not garbage collecting session?

I’m then checking that after 60 seconds and would expect it to be cleared by PHP’s session garbage collector but it’s still there:
I'm aware of how PHP's garbage collection works in that it's not run on every request (1/100 chance by default, defined by other PHP session settings).

I think you answered your own question?  From: https://secure.php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime

session.gc_maxlifetime specifies the number of seconds after which data will be seen as 'garbage' and potentially cleaned up

That means after 60 seconds the value in session has a 1/100 chance of being picked up by the garbage collector.  Of course, you can affect that percentage via other settings, but there are some valid reasons why you would not want garbage collection to run on every request.
I'm not aware of any way to force the PHP garbage collector to run and clean certain values.  I'd probably look at using cache based methods instead since you can set expiration times on cached items.


A single line in my gitignore file, CSS was preventing the Admin CSS from deploying to the live server. While this problem isn't specific to Craft, I'm leaving it here in case others encounter the issue.

That line only prevented folders named CSS from deploying, which is why the public site CSS deployed without a problem, making the problem less obvious.


admin pages loading but not site itself, strange error

Apparently this is a bug in the latest release.  Oops!

The default homepage template on a fresh install is referencing an entry.heading that no longer exists.

Fixed it for the next release, but in the meantime, you can change line 23 of craft/templates/index.html from:

{{ entry.heading }}

to:

{{ entry.title }}


In Craft 3 this is now {{ craft.app.request.absoluteUrl }} — for those who land here from a search and want to avoid using the deprecation notice to update it!


This is nitech from the future. You need to read up a bit. While you built RC Planes from FliteTest with your kids, I went ahead and read up a bit for you:

Webhooks is a concept, not a technology

Webhooks are to apps what push notifications are to us. Remember when you had to check your email to know if there was a new mail? Not any more. Technically speaking, webhooks are "user-defined callbacks made with HTTP". They are usually triggered by some event happening in the source app.

Nitech, you're familiar with HTTP-requests, right? It's kinda the way the web it built. A webhook is simply a POST request typically containing JSON, like this one, coming from your ERP-system:

{
  "sku" : "JU40000365",
  "price" : "29999",
  "stock" : "9"
}

It says: Product with SKU JU40000365 has changes - and they're included in the JSON.

The power of Webhooks is that they're triggered by the source app

Okay, I made that one up. But that's my understanding anyhow. The source detects a change - through whatever mechanism (event, polling, whatever), and triggers a webhook, if there is a webhook configured for that change.

It's the way PayPal tells your shop that the purchase of order 123 was successfully paid - or declined.

How to accept incoming webhooks

So, back to your question - atm. you have to create a plugin or module for Craft CMS in order to handle incoming Webhooks.

If you have a look at Rias' Stripe Webhook Plugin for Craft, you can easily build your own plugin for your specific purpose. Look specifically at the controller.

Also have a look at the Craft 3 documentation, How to build a plugin, which gives you what you need to scaffold and load a plugin into your Craft CMS repo.

I used pluginfactory.io to create a scaffold for the plugin.

In finishing, you may ask why I can't simply just give you a zip-file with the finished plugin. My answer is that you'll be better off experimenting and learning this yourself.


Image and italics issues in Rich Text editor since 2.5 update

There is a better way! Pixel & Tonic has addressed this with the Redactor I plugin, available here: https://craftcms.com/news/running-redactor-i-in-craft-2-5

This completely restores the previous content rendering and functionality (including image sizing/alignment and Live Preview).

I understand where Imperavi is coming from, championing for cleaner data, but it just wasn't part of this project's workflow. When I start my next project fresh, I'll be using Redactor II.


Uploading Assets - PNG changed from 72 dpi to 96

1) why?

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

  2) why is this not spelled out clearly in the documentation?

Good point... we should probably mention it in the Assets section of the docs, or perhaps a knowledge base article. Will look into it.

  3) Shouldn't Craft alert the user that it's altering your image so you don't spend hours trying to figure out what happened to your carefully planned images?

It would get old soon, considering it happens for 99% of uploads.

  4) how can I stop this from happening?

Nothing natively, but you can bypass the whole process by manually FTP'ing up the images and running the Update Asset Indexes utility so Craft picks them up.

Worth noting that you might be better/more consistent results if your server is using Imagick over GD and make sure you're running a recent version of it.

There is a setting to this for GIFs you can disable mainly because animated GIFs  can contain hundreds of frames and transforming those can bring a server down. https://docs.craftcms.com/v3/config/config-settings.html#transformgifs


Craft 2 CMS - How to change Limits in Dashboard

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

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


How can I disable/decrease the number of calls to getAuthTimeout?

Unfortunately, the AJAX call to getAuthTimeout is hard coded to fire every 60 seconds. In other words, if you're looking for a config value, there isn't one – might be worth a feature request?

For a quickfix/hack, you can create a custom plugin and add the following to its init method:

craft()->templates->includeJs('(function () {
    Craft.AuthManager.checkInterval = 600; // Ten minutes
}());', true);

You can change the 600 to any number of seconds, of course.

If you want to kill the timeout check completely, you can do this instead of the above:

craft()->templates->includeJs('(function () {
    Craft.AuthManager.prototype.setCheckAuthTimeoutTimer = function () {};
}());', true);

Of course, both of these snippets are total hacks. Use with caution!

One important thing to note is that I don't think its possible to stop the first AJAX call to getAuthTimeout (which will fire after 60 seconds). The reason is that by the time the JavaScript hack inside the includeJs handler has fired, the Craft.AuthManager class has already been initialized and created the first timeout object. There's no reference to this timeout stored anywhere on the Craft object (that I've been able to find, at least), which makes it impossible to clear it, unfortunately.


Matrix getBlockTypesByFieldId() function doesn't work as intended?

Turns out this was a bug in Craft and we've just fixed it for the next (post build 2568) release.


Can't search for drafts in Control Panel

As per 3.6.5, drafts meta data have become searchable (not custom field) and you can (re)index them by running:
php craft resave/entries --drafts --update-search-indexes

In terms of filtering, you need to manually selete Live to hide drafts from the listing.