Is it possible to use the ElementType Modal UI for a custom Field Type Plugin?

Yep, you can do that with Craft.createElementSelectorModal():

var myModal = Craft.createElementSelectorModal('Entry', {
    resizable:          true,
    storageKey:         'someUniqueID',
    sources:            ['section:1', 'seciton:2'],
    criteria:           { status: null },
    multiSelect:        true,
    disabledElementIds: [1, 2, 3],
    disableOnSelect:    true,
    onCancel:           function(){},
    onSelect:           function(entries){}
});

The first argument specifies what type of element you want to be selecting (Entry, Asset, etc.), and the second argument defines the settings.

All of those settings are optional except for onSelect. Here’s what they do:

resizable (bool) – Whether the modal should be user-resizable. (Defaults to true)
storageKey (string) – The storage key prefix that the modal will use to save its state in the browser’s localStorage, including things like which source was selected. (Defaults to null)
sources (array) – Which sources should be shown in the modal’s sidebar. If omitted, all sources will be shown. (Defaults to null)
criteria (object) – The params that will be used to determine which elements will be shown. See the craft.entries documentation for available params when selecting entries. (Defaults to null)
multiSelect (bool) – Whether multiple elements should be able to be selected at once. (Defaults to false)
disabledElementIds (array) – A list of element IDs that should be disabled (unselectable). Pass any elements that are already selected in here, so they can’t be double-selected. (Defaults to an empty array)
disableOnSelect (bool) – Whether the modal should automatically disable elements when they are selected. (Defaults to false)
onCancel (function) – A function that should get called when the modal is cancelled without selecting anything.
onSelect (function) – A function that should get called when elements have been selected.

The onSelect function will get passed an array that contains info about each of the selected elements. Each item in the array will have the following properties:

id – The element’s ID
label – The element’s label (the Title if it’s an entry)
status – The element’s status
url – The element’s front-end URL, if it has one
hasThumb – Whether the element has a thumbnail
$element – A jQuery object for the element, which you can append to your field input

Once you’ve created your modal, it will automatically be shown. It will also be automatically closed when it is cancelled out of, or elements are selected.

You can re-open it later by calling myModal.show().


Image Upload "Failed to load resource: the server responded with a status of 500 (Internal Server Error)"

UPDATE

Got an answer here. It was me the problem the whole long. I read through my error logs (thanks Brad on that!) and found out that I had that the my php's gd extension wasn't active. I activated and I now have it working!
Thanks for all the help!


Its not at all difficult. Here's the example form from the docs:

https://craftcms.com/docs/templating/user-registration-form

<form method="post" accept-charset="UTF-8">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="users/saveUser">
    <input type="hidden" name="redirect" value="">

    {% macro errorList(errors) %}
        {% if errors %}

                {% for error in errors %}

{{ error }}

                {% endfor %}

        {% endif %}
    {% endmacro %}

    {% from _self import errorList %}

Username

    <input id="username" type="text" name="username"
        {%- if account is defined %} value="{{ account.username }}"{% endif -%}>

    {% if account is defined %}
        {{ errorList(account.getErrors('username')) }}
    {% endif %}

Email

    <input id="email" type="text" name="email"
        {%- if account is defined %} value="{{ account.email }}"{% endif %}>

    {% if account is defined %}
        {{ errorList(account.getErrors('email')) }}
    {% endif %}

Password

    <input id="password" type="password" name="password">

    {% if account is defined %}
        {{ errorList(account.getErrors('password')) }}
    {% endif %}

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

And you can find a login form here: https://craftcms.com/docs/templating/user-profile-form

And a profile editing template here:
https://craftcms.com/docs/templating/user-profile-form

Also remember that you can use all kinds of custom fields on your users


How do I use a Dropdown 'Entries' Field Type in a Front End Form

Simply put, an Entries field is an array containing entry ids, and your form needs to send it that way.

Just replace name="fields[tbdDesignerUrl]" with name="fields[tbdDesignerUrl][]". That way the value gets submitted as an array.

Also replace value="{{ entry.designerUrl }}" with value="{{ entry.id }}", since we need the submitted value to be an entry id.


Using the Search Filter with Entry Fields

{% set range = entry.model %}
{% set categories = craft.categories.slug('not preferential') %}
{% set entries = craft.entries.section('offers').search('title:' ~ range).relatedTo(categories) %}

If you are only searching titles I would add that in the search params as it will help the effectiveness of the search. In addition when setting a variable you do not need to use the {{}} syntax as it will automatically use the string representation of the the field if it is a text field.


Problems with tasks and max execution time

Tasks are just another PHP request and they are subject to the same web server and php.ini limitations as a "normal" request.

Sounds like you just need to up your max_execution_time.


Craft Commerce Arrange a delivery booking plugin?

I'm not aware of an existing plugin for Craft/Commerce that would do this and a search through https://straightupcraft.com/craft-plugins/ doesn't reveal much more.

Sounds like it would need to be custom plugin development.


This is actually pretty simple...

If you navigate to SEOmatic → Site Settings → Miscellaneous, you'll see a table at the bottom of the page where you can input custom sitemap urls.

Once you add a url in here and save it, it will get added to a custom index sitemap that is included at the bottom of your main index sitemap:

/sitemaps/1/sitemap.xml

<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  ...
  <sitemap>
    <loc> http://site.test/sitemaps/1/global/custom/1/sitemap.xml </loc>
    <lastmod> 2018-11-16T10:06:31-05:00 </lastmod>
  </sitemap>
</sitemapindex>

/sitemaps/1/global/custom/1/sitemap.xml

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc> http://site.test/custom.xml </loc>
    <lastmod> 2018-12-07T14:26:25-05:00 </lastmod>
    <changefreq> weekly </changefreq>
    <priority> 0.5 </priority>
  </url>
</urlset>

for more info → https://github.com/nystudio107/craft-seomatic#additional-sitemap-urls


How to change the Slug in case of copied entries?

Seems like a good case for a simple plugin that listened to the onBeforeSaveEntry event.

That plugin could verify the entry is in the section you're looking for, compare the existing slug against any saved in the database and do whatever you want to do from there (set it null, etc.).


Unfortunately it’s not possible for an included template to override the contents of a block in the parent template, or its layout.

You’d need to just override the seo block from page.twig do whatever you need to do from there instead.

{% extends 'layout.twig' %}

{% block main %}
  some content..
  {% include 'pagination.twig' %}
{% endblock %}

{% block seo %}
  <link href="url" rel="canonical">
{% endblock %}


As of Craft 2.6, this is now possible!
In fact, it works exactly like your first example:
{% case "A" or "B" or "C" %}
  {# run this if case matches A or B or C #}

Original answer...
Your first example is not currently possible, but might make for a good feature request.
Your second example is not possible, and most likely never will be. If it were added in the future, that would likely have a major (breaking) impact on all existing uses of the switch statement.
The way that Craft has implemented the case statement is by making it completely unnecessary to supply a break statement. In fact, the break statement doesn't even exist natively (though can be added with the MN Break and Continue plugin). The case statement will automatically end when it hits the next case statement, or the endswitch statement.
An actual solution would be to use a macro or include. If you have multiple case statements which should trigger the same behavior, I'd recommend wrapping that behavior into a macro/include, and calling that macro/include for each relevant case.


One issue may be that your javascript is requesting a specific url as defined from the site root, thus not giving craft the opportunity to do it's locale routing magic (keep in mind the url for languages other than the default locale may actually be '/no/loadmore.html' — or however you have defined the locale routes in your config settings). So just changing the request url in javascript may solve the problem.

$('.third_article_module').load('loadmore');

Another thing to keep in mind in general is that you can always specify a locale as part of the query, if you ever need to bypass or override craft's locale routing for some reason.

{% set locale = craft.i18n.getCurrentLocale() %}
{% set entries = craft.entries.section('artikkel').locale(locale).order('dateCreated desc') %}
{% for entry in entries %}
    ...
{% endfor %}

Another thing worth mentioning is that you could potentially also ajax load content from the current page template by using an isAjax conditional, thus eliminating the need for a separate 'loadmore' template altogether.

{% if not craft.request.isAjax %}
    {# render page content #}
{% endif %}

{% if craft.request.isAjax %}
    {# render loadmore content #}
{% endif %}

You can then just pass the entry url to your javascript and ajax load the current page (in this case I'm passing the url by defining a 'data-url' attribute on the .showmemore_inner h2 dom element; i.e. <h2 data-url="{{ entry.url }}">).

$('.showmemore_inner h2').on("click", function(e){
    e.preventDefault();
    var url = $(this).attr('data-url');
    $('.third_article_module').load(url);
    $('h2.lasterinn').css('display', 'block');
});

Note: also e.preventDefault() should come before any return statement or else it will never get a chance to fire.


You can easily measure the time your request takes using JS.

See this Stack Overflow question for example code: https://stackoverflow.com/questions/3498503/find-out-how-long-an-ajax-request-took-to-complete

var start_time = new Date().getTime();

jQuery.get('your-url', data,
    function(data, status, xhr) {
        var request_time = new Date().getTime() - start_time;
    }
);


MySQL ColumnType::Time does does not populate model from setAttribute()

It turns out that I don't think you should really use craft's DateTime object for time only. I suppose there is a case where you might want but if you just have a "time of day" absent a date, I ended up using AttributeType::String for them, but still use a ColumnType::Time for the database.

Then all I needed to do is override populateModel method to do a little magic to convert them from 24 hour format to 12 hour format like this:

public static function to12Hour($dbTime) {

    $dbTime = explode(":", $dbTime);

    if($dbTime[0] > 12) {
        $ampm = "PM";
        $dbTime[0] = $dbTime[0] - 12;
    } else if($dbTime[0] == 0) {
        $ampm = "AM";
        $dbTime[0] = 12;
    } else {
        $ampm = "AM";
    }

    return $dbTime[0] . ":" . $dbTime[1] . " " . $ampm;
}

public static function populateModel($values) {

    $model = parent::populateModel($values);

    if ($values['startTime']) {
        $model->setAttribute('startTime', self::to12Hour($values['startTime']));
    }

    if ($values['endTime']) {
        $model->setAttribute('endTime', self::to12Hour($values['endTime']));
    }

    return $model;
}

You just need to make sure you're storing the time in 24 hour format and to ensure that is the case, I set up my attribute types like this:

        'startTime'         => array(AttributeType::String, 'column'=>ColumnType::Time, 'required' => true, 'matchPattern' => '/^\d\d:\d\d:\d\d$/'),
        'endTime'           => array(AttributeType::String, 'column'=>ColumnType::Time, 'matchPattern' => '/^\d\d:\d\d:\d\d$/'),


Your answer didn't end up working for me, but I did get it working.

Update (or add) "vlucas/phpdotenv": "^5.0" to composer.json
Edit the craft (or index) file's contents:

// Load dotenv?
// if (class_exists('Dotenv\Dotenv') && file_exists(CRAFT_BASE_PATH.'/.env')) {
//     Dotenv\Dotenv::create(CRAFT_BASE_PATH)->load();
// }
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
if (file_exists(CRAFT_BASE_PATH.'/.env')) {
  $dotenv->load();
}

I can then retrieve my environment vars with:
$varOne = $_ENV['VAR_ONE'];
$varTwo = $_SERVER['VAR_TWO'];


Craft equivalent to Drupal Signups module

For the calendar portion:

Solspace Calendar: https://solspace.com/craft/calendar

Craft Calendars: https://topshelfcraft.com/calendars/introduction

For the membership part it'd be pretty easy to just add the people who register onto the event itself


Update: This bug is fixed as of Craft 2.4.2697

  Images uploaded from iOS now get renamed to
  “image_YYYYMMDD_HHMMSS.ext” (from “image.ext”), fixing a bug where iOS
  uploads would fail after the 51st image due to Craft’s limit on
  allowed same-name uploads.

iOS uploads images from the camera roll with the name image.jpg, and if this happens multiple times then an incremental number is appended to the filename, similar to what happens with slugs. I have found that after 50 such instances though, the error message you reported starts to appear and images cannot be uploaded.

This is a bug in Craft and P&T will hopefully release a fix soon, but a temporary solution is to rename some uploaded files so that the 50 limit is not reached. Alternatively, you could make the entry slug part of the upload path to avoid reaching the limit.


How do I validate an array model attribute against a set of possible values?

Found an answer in the form of a customer validator class on the model:

https://experiencehq.net/blog/the-definitive-guide-to-validation-in-craft-part-5-custom-validators#newsletter

So something like this:

    public function validateMySetting($attribute)
    {
        $values = (is_array($this->$attribute)) ? $this->$attribute : [ $this->$attribute ];

        $validValues = ['validOption1', 'validOption2', 'validOption3'];

        foreach($values as $value)
        {
            if ( ! in_array($value, $validValues))
            {
                $this->addError($attribute, "{$value} is not a valid setting");
            }
        }
    }

And then to call it, override the parent class' rules method:

public function rules ()
{
    return array_merge(parent::rules(), [
        'someAttributeName', 'validateMySetting'
    ];
}


There are several things that might be the issue in such cases, I'll list a few of them

Did you change your index.php so maybe Craft is unable to detect the current site?
Are there different index.php files in different folders in order to do the multisite setup instead of the single one? -> You should only have one for all
Do you have any plugins that might interfer and offer their custom error page / error behaviors?
Do you have any other events in your own custom plugin/module that includes a custom error handling?
Is your error template in the templates roots folder and not in a site/site group subfolder so Craft only selects it for a single site instead of globally?
Make sure dev mode is off


What's the difference between 'user', 'currentUser', and 'account'?

Update:
As of Craft 3.x, the deprecated user variable no longer works. Make sure to use the proper currentUser variable instead!

Original:
user and currentUser are exactly the same. They contain the UserModel of the currently logged in user.
Why are they exactly the same? Originally, user was the preset value for the current user. However, there were many cases of people manually setting a value for user (often in the context of a for loop through a group of users), and therefore overwriting the preset value. So P&T introduced currentUser as an alias which was much less likely to be overwritten.
account will only exist on the User Registration Form. Its value is automatically set when the form is submitted. account represents the values entered during the attempted registration (whether the registration was successful or not).
For the sake of your Edit Profile pages, you'll want to use currentUser.


After switching from PHP 5 to 7 for a local 2.x install, I can't login

Turns out that it was a PHP configuration issue.

Under Windows, the paths in php.ini need to include a drive letter (eg. c:\xampp\php7\). By default they're root-relative (eg. \xampp\php7). When I originally installed XAMPP with PHP 5.x, it adjusted the paths automatically. But when I manually copied the PHP 7 folder into XAMPP to set it up for version switching, I overlooked the path discrepancy.

In this case, it was the inability of PHP 7 to set sessions that was causing the odd behavior.


Locales and links not working as intended

If your entry's slug is en/contact and you need it to show up when you go to the URL domain.com/en/contact/en/contact, the Section settings for the Entry URL Format should be en/contact/{slug}:

Also, you shouldn't need to use the language code prefix (en/) in Section settings. That should be defined in your config/general.php file. See the Define your site URLs section of the Craft 2 docs on localization.

return array(
    // ...
    'siteUrl' => array(
        'en' => 'http://example.com/en/',
        'no' => 'http://example.com/no/',
    ),
);

Then, if you Section's URL settings are contact/{slug}, these URLs will both work:

http://example.com/en/contact/en/contact
http://example.com/no/contact/en/contact


User-determined price for a product variant?

Here's how you could accomplish this.

1) Create a product variant called 'custom amount' with a zero price.

2) Get the ID of that variant

3) When submitting/adding/updating the item to the cart make sure to post an 'amount' line item option. For docs on that see: https://docs.craftcms.com/commerce/v2/adding-to-and-updating-the-cart.html#line-item-options-and-notes

3) Create a plugin/module that attaches this listener:

Event::on(LineItems::class, LineItems::EVENT_POPULATE_LINE_ITEM, function(LineItemEvent $event) {
    $lineItem = $event->lineItem;
    $purchasable = $lineItem->getPurchasable();
    if($purchasable && $purchasable->id = ID_OF_VARIANT_HERE)
    {
        $amount = $lineItem->options['amount'] ?? 0;
        if($amount)
        {
            $lineItem->price = $amount;
            $lineItem->salePrice = $amount;
        }
    }
});

This will set the price to the price of the line item option 'amount' that is submitted.


Is it possible to use Twig in a Rich Text Field?

The Technical Way

You can do this using Twig's template_from_string function and the raw filter.  In your template code you would output your Rich Text field:

{{ include(template_from_string(entry.richTextFieldHandle)|raw) }}

And within your Rich Text field you could reference your global with the same syntax you normally would in Twig as you described above:

This is a rich text field, call us today at {{ phone.number }}!

A More User-Friendly Way

The Rich Variables Plugin allows you to give a user control over adding Global Variables to your Rich Text field.

This approach will be a bit more limited in what you can accomplish, but probably toward a more user-friendly outcome for your content managers.


This might be considered more of a "workaround" than a technical solution, but I think it could actually solve your problem quite nicely...

You can use CP CSS and/or CP JS to show or hide certain fields.

You'll probably find that the CP Body Classes plugin is helpful for narrowing in on specific conditions. For example, you could show/hide certain fields based on a specific user group.

Disclaimer: I wrote each of those plugins. Feel free to leave feedback on Github!


Update a user image on the front end using Vue.js and Ajax

In the end I found a solution which doesn't require creating my own controller. I am not sure it is possible to post directly to the $_FILES array in Craft but by using the native FormData object in Javascript you can basically pass all the form fields in the correct format to the vue-resource post method. I found this article useful on my search for solving what I needed. In doing this it kind of bypasses the Vue data model which is not exactly what I was after but it works well and keeps things simple. One caveat is that support for the FileData object is only on modern browsers but you can polyfill for older browsers.

Here is my final test form code:

<form method="post" action="" enctype="multipart/form-data" accept-charset="UTF-8" @submit.prevent="submitForm" id="imageForm">
  {{ getCsrfInput() }}
  <input type="hidden" name="action" value="users/saveUser">
  <input type="hidden" name="redirect" value="members/profile/{% include '_includes/helpers/user_profile_link' %}">
  <input type="hidden" name="userId" value="{{ currentUser.id }}">

  {% if currentUser.photoUrl %}
    <transition name="fade">

    </transition>

    Delete

    <input type="hidden" name="deleteUserPhoto" id="deleteUserPhotoInput" value="" v-model="user.deleteUserPhoto">

      Member Image
      <input id="avatar" type="file" name="userPhoto">

  {% else %}

      Member Image
      <input id="avatar" type="file" name="userPhoto">

  {% endif %}

  <button type="submit" class="button is-primary">Save Profile</button>
</form>

Here is my final Vue.js code:

Vue.http.options.emulateJSON = true;
Vue.http.options.emulateHTTP = true;

var app = new Vue({
  delimiters: ['@{', '}'],
  el: '#app',
  data: {
    user: {
      deleteUserPhoto: '',
      userId: '{{ currentUser.id }}',
      action: 'users/saveUser'
    },
    showImage: true
  },
  methods: {
    submitForm: function() {
      var form = document.getElementById('imageForm');
      var formData = new FormData(form);

      this.$http.post('/', formData)
        .then(function(response) {
          //this.updated = true;
        });
    },
    deletePhoto: function () {
      this.user.deleteUserPhoto = 'noMorePhoto';

      var data = this.user;

      data[window.csrfTokenName] = window.csrfTokenValue; // Append CSRF Token

      this.$http.post('/', data)
        .then(function(response) {
          this.showImage = false;
        });
    }
  }
});


craft.entryRevisions.getDraftsByEntryId(entry.id) is returning an empty array

Specify the locale when getting the drafts, or else it will fetch drafts for the default locale. In my case, there was only drafts for a particular locale but not the default.

{% set drafts = craft.entryRevisions.getDraftsByEntryId(entry.id, 'localeId') %}


There is a purify and a Clean-up option on a WYSIWYG field.

Clean up HTML? – Whether Craft should run through some HTML cleanup routines when the field is saved, including removing all  tags, empty tags, and most style attributes.

Purify HTML? – Whether the field should run submitted data through HTML Purifier before getting saved to the database, removing any potentially malicious code. Note that this is meant to be be used when accepting input in a Rich Text field from un-trusted sources.

Turning the purify off, let's you output HTML. That being said, I'm not sure of what you are trying to achieve but inserting raw HTML into a WYSYWIG field isn't really the way to go about things. Maybe if you share the bigger scope of the issue, we can look into a better approach of your problem.

source: https://craftcms.com/docs/rich-text-fields


Inconsistent search results in multi-site setup (prod/stage)

The resave/entries command has an optional parameter to rebuild the search indices - may be worth a shot:
./craft resave/entries --update-search-index
https://craftcms.com/docs/3.x/searching.html#rebuilding-your-search-indexes


Restricting Payment Gatways by User Group using Commerce Pro?

This is really more of a Craft general thing than Commerce per se, if you're content to simply 'restrict' them by only showing them the appropriate options depends on their group.
If so, then it's as simple as some twig code to test the user group and show/not show things accordingly.
{% if currentUser.isInGroup('groupHandle') %}
   ... show something
{% else %}
   ... show something else
{% endif %}

(Of course that requires a logged in user and the bigger questions here is whether user groups is the right way to handle this scenario...)
If you want to take things further, you could listen to various Commerce events in a custom module and take action there if they should/shouldn't be allowed to do what they arte doing.  You might look at:
https://craftcms.com/docs/commerce/3.x/events.html#beforeprocesspaymentevent
https://craftcms.com/docs/commerce/3.x/events.html#beforecompleteorder
...or others - they are listed here:
https://craftcms.com/docs/commerce/3.x/events.html
In reality, as usual, probably some combination of front end logic and back end verification would be the way to go.
Hopefully that is enough to get you started!


Does Google Analytics track Live Preview 'page views'?

If you're using SEOmatic - no. It's built in that the GA doesn't get spat out for the preview. If you're using a regular template - yes; you may want to wrap your GA code in a conditional so that it's not spat out when requested via the live preview.

{% if not craft.config.devMode and not craft.request.isLivePreview %}{# GA code here #}{% else %}<!-- Google Analytics script is NOT included in LivePreview or if devMode is on -->{% endif %}

[edit] Whoops, saw the other half of your question. What is it about your set up that's stopping you doing this? Sounds more like an Analytics issue than a Craft one to me.


If that's what you see when you go to the URL, then you probably don't have the server root set properly. It should point to the web/ directory, not the project root.

Some more helpful Craft setup info can be found here: Setting up a New Craft CMS 3 Project

Typically you do the install in local dev, and then have some kind of a deployment process to deploy it to your staging/production servers.


Problem with @font-face url 500 server error craft style

Your css and your fonts should be in the public section of the craft website. So put your css in "root/public/assets/css" and "root/public/assets/fonts/bootstrap". Than remove the {{ siteurl }} twig code (in this therme only use plain css).


Paginate events without setting expiry date

You need to include an extra parameter in your initial query to only fetch event entries for events in the future and remove the conditional test from the for loop.

Currently you are fetching all event entries and paginating those, but only displaying event entries where the eventDate is in the future.

Try this instead:

{% paginate craft.entries.section('eventsEntry').limit(3).eventDate('>=' ~ (now | date('Y-m-d H:i'))).orderBy('eventDate') as pageInfo, upcomingEvents %}

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


You need to allow the entry.type value to be part of the include path...

{% include "events/_types/" ~ entry.type %}

Since your entry.type is "summerpreview", that will be parsed out like this...

{% include "events/_types/summerpreview" %}

With Craft, you don't need to specify the .html extension, so this include should work perfectly.

As a side note... I'd recommend turning on devMode locally. It would have thrown an error, telling you that summerpreview is not a legitimate variable.

  What Dev Mode Does


Craft doesn't natively set a cookie named TS#, so it's either coming from something in your front-end templates or possibly from a plugin you've got installed.

You can read about the CraftSessionId cookie and all other cookies that Craft uses by default here: https://craftcms.com/support/how-does-craft-use-cookies


Merge Entries but only after X amount of entries

Seems like a rather specific edge case, so I'd be surprised if there's something built in (nothing comes to mind). However, you could write a custom twig filter fairly easily to do this.


OK, so this did have a really simple solution. Just use isDefault.

{% if variant.isDefault %}Show the product{% endif %}

Works like a charm.


It can be done with some Twig code:

{% set referrer = craft.request.urlReferrer %}

{% if referrer %}
    {# Remove everything before the `?` #}
    {% set queryString = referrer|replace('/^.*\\?/', '') %}

    {# Split the query string into individual params #}
    {% set params = queryString|split('&') %}

    {% for param in params %}
        {# Split this param on the `=` sign #}
        {% set parts = param|split('=') %}
        {% set name = parts[0] %}
        {% set value = parts[1] is defined ? parts[1] %}

        {# Do something with it... #}
    {% endfor %}
{% endif %}

Note that this could would require Craft 2.2 or later, which comes with a regex-enabled replace filter.


Trim trailing spaces before each new line in a multi-line string

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

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

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

UPDATE

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


craft()->locale->getTimeFormat() throws Fatal error

I had the same issue. In our case it were the i18n and the vendor files that were being excluded by a too restrictive gitignore file.

Never use the default gitignore from Craft 3 on a Craft 2 setup. :-)


You probably don't have an Asset Volume defined yet. The button won't show up if there are no Asset Volumes, regardless of what your Redactor config specifies.

  To add an Asset Volume, visit the Settings section of the admin, click "Assets," and then "Volumes." By default, only the "Local" Volume type is available, but you can install additional Volume types through the Plugin Store.


How do you require specific dimensions when uploading an image?

Currently, no. The only file-based validation Assets fields have right now is the type. If you want to enforce a certain size, you can do that on the template end using image transforms. I would suggest adding some instruction text to your Assets field that provides a minimum suggested size, and note that smaller images will be scaled up and look gross.

That said, if you really want to enforce a minimum width/height, or other properties, you can do so by writing a plugin that provides its own field type, which extends AssetsFieldType and overrides its validate() method with your custom validation:

public function validate($value)
{
    // Let AssetsFieldType do its validation first
    $errors = parent::validate($value);

    if (!is_array($errors))
    {
        $errors = array();
    }

    if (is_array($value) && !empty($value))
    {
        foreach ($value as $fileId)
        {
            $file = craft()->assets->getFileById($fileId);

            if ($file)
            {
                if ($file->width < 600 || $file->height < 400)
                {
                    $errors[] = Craft::t(
                        '{filename} must be at least 600x400px.',
                        array('filename' => $file->filename)
                    );
                }
            }
        }
    }

    if ($errors)
    {
        return $errors;
    }
    else
    {
        return true;
    }
}


It is stored in 4 decimal places because some currencies have more than 2 decimal places.

We round before multiplication because we need don't store any value on the line item in a number of decimal places larger than the base currency. This allows us to add up line items without creating new cents.

As you suggest this could be changed to CommerceCurrencyHelper::round($this->qty * $this->salePrice); but this would be a breaking change for other users. We will consider it for Commerce 2.

I don't recommend using > 2 decimal places to accomplish your "12 for 6.99" offer, rather make a discount adjuster that reduces the regular price of line item with a discount if qty modulo 12 = 0.


How can I let the user activate a particular SuperSort filter

So in order to do this you have to reformat your code and your strategy a bit. You cant provide a Craft query as a link, all that does is grab an array from the database and it won't inherently print something out.

A-Z

The best way to change the way your results are being sorted (if you want to do it via Twig and not something front-end like JS is to send the sort style through a query string.

So let's assume you are returning a list of users and you want to sort them by first name alpha ascending:

{% set users = craft.users.order('firstName asc').find() %}

If you want to change the direction of the order create a link like this:

Sort Z-A

When the page reloads a new query parameter is available to you sort, you can get it with this code:

{% set sort = craft.request.getParam('sort') %}

Now you can use that variable to alter the way your original query works. Something like this... starting over from scratch:

{% if craft.request.getParam('sort')|length > 0 %}

    {% set sort = craft.request.getParam('sort') %}

 {% else %}

    {% set sort = 'asc' %} {# default sort #}

 {% endif %}

Then in the Craft query, you could just user this instead of our original query above:

 {% set users = craft.users.order('firstName ' ~ sort).find() %}

Now when the page first loads you will get users sorted by firstName asc and when you click the filter it will reload with firstName desc.

You can apply this same query string method to all of the parameters. Getting variables like:

{% set sortBy = craft.request.getParam('sortBy') %}

Where sortBy equals firstName or lastName

That query string would look like:

url/user-list?sort=desc&sortby=firstName

And so on.


Filtering/searching for entries by category in the control panel

You can via the search box:

myCategoriesField:"some category title"

See http://buildwithcraft.com/docs/searching for details on the syntax.

We do plan on making it possible to add category/tag filters to the element indexes though, including the modal selection windows.

Update: You can add a list of categories to the Entries page sidebar using the Category Sources plugin.


Craft CMS throws Internal Server Error 500

Based on the error message and this: https://php.watch/versions/8.0/deprecated-reflectionparameter-methods, it sounds like you're running PHP 8, which Craft isn't compatible with, yet.
The soon-to-be-released Craft 3.6 adds PHP 8 compatibility, so you'll want to downgrade to PHP 7.4 until that's out.


Paginate entries when I do not have a criteria model?

This is in no means an elegant solution, and can almost certainly be improved. But it did its job just fine.

{% set veterinarians = craft.entries({
    section: 'veterinarians',
    order: 'premiumVet desc, postDate desc',
}) %}

{# more filter/search params #}

{% set entriesPerPage = 20 %}
{% set page = craft.request.getParam('page') %}
{% set page = page ?: 1 %}
{% set offsetParam = (page - 1) * entriesPerPage %}

{% set veterinarians = veterinarians.offset(offsetParam).limit(entriesPerPage) %}

{% set isNextPage = veterinarians.offset(page * entriesPerPage).limit(1)|length %}
{% set queryString = craft.request.getQueryStringWithoutPath()|replace('/page=\\d+&?/') %}
{% set queryString = queryString ? '&' ~ queryString %}
{% set nextUrl = isNextPage ? craft.request.url ~ '?page=' ~ (page + 1) ~ queryString %}

{% for entry in veterinarians %}
    {# loop entries #}
{% endfor %}

{% if nextUrl %}

        Weitere anzeigen

{% endif %}


Change currency in Craft CMS using the Charge plugin

Developer of Charge here.

It sounds like you could be running an older version of the Charge.  There was a display bug on the overview page that would set the currency symbol incorrectly for some setups.

This is fixed in the latest versions, so make sure you're running 2.2.0 or above.

Note - this fix won't affect any previously recorded payments that were in a non-default currency, but this is purely a display bug on the overview page - if you go into the detail view for the specific Charges, they'll be correctly showing the relevant currency, and all the details visible to the end-customers and on Stripe will also be correct.


You'll need to create custom route to access those files. This is just an example of a custom route in my current module, so you need to find a pattern that matches the one you receive from the tool

$event->rules[] = [
    'pattern' => '/userfiles/<fileType:\w+>/<fileName:\S+>',
    'route'   => 'thaff/profile/get-file'
];

And your Controller action could be something like this

public function actionGetFile($view, $fileName)
{
    // create an alias to your folderpath $view should be thumb/mobile-ext or mobile depending on the route
    $localPath = Craft::getAlias('@yourFolderAlias') . DIRECTORY_SEPARATOR . $view;

    // you can include several checks if the image should be visible for the current user or not...

    $resp = Craft::$app->getResponse();
    $resp->headers->set('Content-Type' /*, insert your mime-type here */);
    $resp->format = Response::FORMAT_RAW;
    // check if the file exists
    if ($localPath && file_exists($localPath . $fileName)) {
        // open the file
        $handle = fopen($localPath . $fileName, 'rb');
        // send the result to your response object
        $resp->stream = $handle;
        // send the response and close the file
        $resp->send();
        @fclose($handle);
    }
}

Note: this is just a little code snipped of my current project and I removed many conditional checks so it's easier to read.


Throwing 500 error, but nothing logged in error logs or apache logs?

It's likely environmental/configuration related and unfortunately some hosts do some things to make it really hard to debug stuff like this.

Off the top of my head, some common ones are if you've got something like Suhosin or mod_security installed, then they have their own configuration limits on top of the usual PHP/Apache limits that might be coming into play.

Or if you're running nginx/php-fpm as a proxy in front of Apache, you might be bumping into its configuration limits.

Or we've seen some hosts <cough>RACKSPACE</cough> that have hard-coded execution times of 30 seconds at the router/firewall level and there is absolutely nothing you can do to get around it, other than the obvious thing, which is to never use Rackspace.


Is there a JavaScript event available for when the parent tab of a custom field is shown?

There is not, however if you have a Javascript class that extends Garnish.Base, you will be able to listen for a custom resize event on your container div using Garnish.Base::addListener(), which will trigger when the element first gets a height.

window.MyClass = Garnish.Base.extend(
{
    container: null,

    init: function(container)
    {
        this.$container = $(container);

        // Is the container already visible?
        if (this.$container.height())
        {
            this.doStuff();
        }
        else
        {
            // Hold off until it is
            this.addListener(this.$container, 'resize', function(ev)
            {
                this.removeListener(this.$container, 'resize');
                this.doStuff();
            }
        }
    },

    doStuff: function()
    {
        // this.$container is visible now
        // ...
    }
});

Off-topic, but worth noting: one of the benefits of using Garnish.Base::addListener() rather than jQuery.on() or jQuery.bind() is that it will maintain the scope for you in the callback function. So you don’t need to worry about doing that yourself with jQuery.proxy(), e.g.

this.$container.bind('click', $.proxy(function(ev)
{
    // `this` would refer to the container element here, if it weren’t for $.proxy().
}, this);


Modifying entry with 'onBeforeSaveEntry' event

Sprout SEO is a conjunction of different fields when you save an entry it will send the values from the Sprout SEO field (title, description, ogImage, etc..) in the 'metadata' namespace. So, in order to override this value, you can follow the next example:

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

       if($entry->type['handle'] === 'service'){
          $serviceContent = $entry->linkToService->first();

          $seo = $entry->getContent()->seo;
          $seo['metadata']['optimizedDescription'] = "Override description value";
          // Update it in the post request
         $entry->setContentFromPost(array('seo' => $seo));
      }
});

In this example I override the 'optimizedDescription' you can see all the properties in the 'sproutseo/models/SproutSeo_MetadataModel.php' File.

Remember that you can also override any value on the front-end using Template Overrides or add a Custom Format to specific values like the title or description using twig logic on your Sprout SEO field settings


There's a typo in your code :) You misspelled relatedTo. I'm assuming that's the issue because other that than, the code looks like it should work.


Correctly using eager loading in Plugin development

Eager loading only works when your field is a RelationField it does not work with Text fields. If you goal is to reduce the length of the queries and to maximize your performance you could fetch the raw rows instead of populating the elements.

$criteria = craft()->elements->getCriteria(ElementType::Category);
$criteria->status = null;
$criteria->limit = null;
$criteria->group = 'productBrand';

// create a query
$query = craft()->elements->buildElementsQuery($criteria);
// select only the rows you want/need
$query->select('elements.id as id, content.field_posBrandKey as posBrandKey');
$brands = [];
// execute it
$rows = $query->queryAll();

foreach($rows as $row){
    $brands[$row['posBrandKey']] = $row['id'];
}


Plugin, getting an entry when one of multiple category fields and/or lightswitches are not empty/turned on

If found the answer. You can use an * operator in the search query to check if a category field is not empty. So the solution in my case was:

'search' => lightswitchOne:1 OR lightswitchTwo:1 OR lightswitchThree:1 OR categoryOne:* OR categoryTwo:*


getResourcePath() for folders in a plugin

The ResourcesService getResourcePath method will only work for files.

The PathService getResourcesPath method will get you the resources path, after which you can append your folder name.

$folder = craft()->path->getResourcesPath() . 'svg/';


addFieldVariables not functioning with string data

The value you place in your Hidden Field settings gets treated as a template and whatever values you pass o the addFieldVariables method are treated as the object that gets parsed by that template.

Just like, when you load an Entry page in Craft, Craft provides the entry variable to the template, when we process the Hidden Field settings, Sprout Forms provides the addFieldVariables variables to that template.

While Craft knows it is giving you an Entry and names it's variable entry, Sprout Forms doesn't really know what you might be giving it, so it names the variable available to your settings template a generic term: object.

You can access these values using Object Syntax, in the same way you can using the Title Format behavior for Sections:

{{ object.variableName }}

Or in your case:

{{ object.queryStr }}

In some cases, you can also use a shorthand to output the value with a single curly brace: {queryStr}.


Is FeedMe v2 supporting FTP with basic authentication

FTP should still work just fine in Feed Me 2. You can also use basic authentication by providing the username/password in the URL.

ftp://username:password@website.com/public_html/feed.xml

You can also use the curlOptions settings in the configuration.


What would cause an custom element listing to just return everything?

It is likely just a typo in your template. Can you ensure that if your element type class name is of the format Custom_PluginElementType that your template code is then in the following format:

{% set elementType = 'Custom_Plugin' %}

Or if your element type class name is of the format CustomElementType that your template code is then in the following format:

{% set elementType = 'Custom' %}


Streamlining a loop with a bunch of conditions

I'm not sure if this is better or not but one thing I'd do here is to set some defaults in my include. This also means you don't need to worry about checking whether it's defined or not. You're just checking whether it's true.

{% set options = {
    author: true,
    badge: true,
    date: true,
    magnify: true,
    meta: true,
    thumbnail: true,
} | merge(cardOptions | default({})) %}

    {% if options.badge %}

    {% endif %}

    {% if options.thumbnail %}

    {% endif %}

Heading Goes in Here

        {% if options.meta %}

                {% if options.date %}
                    {% include "_modules/relative-date" %}
                {% endif %}
                {% if options.author %}
                    by John Doe
                {% endif %}

        {% endif %}

Then when I use this include I can pass in an object of options that could overide those defaults. But I only need to pass in values that need to change the defaults. For example here I can set meta to false but can leave all the others to be handled by the default:

{% set cardOptions = {
    meta: false
} %}

{% include "_modules/card" with cardOptions %}

You said this would be included within an entries loop. You could do this in that case:

{% set options = {
    entry: false,
    author: true,
    badge: true,
    date: true,
    magnify: true,
    meta: true,
    thumbnail: true,
} | merge(cardOptions | default({})) %}

{# Wrap the whole card in a conditional #}
{% if options.entry %}
   // Card goes here
{% endif %}

And then in your entries loop you'd do:

{% for entry in entries %}

    {% set cardOptions = {
        entry: entry
    } %}

    {% include "_modules/card" with cardOptions only %}
{% endfor %}

I'd probably use the only option on the include tag to avoid stuff leaking in.

I've also played with options such as:

{% set cardOptions = {
    styleGuide: true
} %}

In my include this option will have a false default I'll have a conditional that checks for it being true and if so it'll ignore any dynamic content and instead I'll output an example of the module with fake content. It's good for testing and for keeping a library of modules.

You could also consider a macro that wraps your include tag. I gave a similar example in a blog post not long ago: Using macros to improve consistency in your Craft CMS templates

{% macro module(type, options = {}) %}
    {% include '_modules/' ~ type with options only %}
{% endmacro %}

And then in your template you'd do something like:

{% set cardOptions = {
    entry: entry,
    meta: false
} %}

{{ module('card', cardOptions) }}

Dunno if any of that helps!


Showing categories in Channel Entry URLs

There's a lot here but I'd start by create 2 different channel sections: Blog and News.

From the front end, that makes it easy to see which entries are associated with what sections and easy to post content into each one. It also makes it easy to filter in your templates what section you're after.

To get your entry URLs setup, it's a little tricker but you can pull it off with some Craft/Twig magic. Setup a new field, make the handle blogCategory, make it a Category relational field, lock it down to 1 category that pulls from your Blog Category Group, and assign it as a field to your Blog section.

When you're creating the channel, set the URL format in your Channel to this:

blog/{blogCategory.first().slug}/{slug}

That little bit of code basically tells Craft to use the category slug of the blogCategorycustom field we just created in part of the url and the slug of the current entry to make the url. Craft treats categories, assets, entries, etc. and other relational fields as an "array" even if you only have one selected so we need to use .first() to use the first one Craft sees.

Now when you go create your blog entry, you're able to set a blog category and Craft will also use it as part of the URL.

BTW: There's no problem routing the Blog/News index pages to a page in a structure but you have to do the heavy lifting that Craft usually automatically routes for you.

In your _layout.html template, you could do something like:

{%if craft.request.firstSegment() is "news" %}
    {#load up news template #}
    {% include '_news/index.html' %}
{%elseif craft.request.firstSegment() is "blog" %}
    {#load up news template #}
    {% include '_blog/index.html' %}
{%endif%}

There's more to it than that, of course but hopefully that might get you started. It takes a little while to get your head around Twig and how powerful it is to use in Craft.

You'll want to also setup URLs for your Categories to have Craft load the appropriate template for each. Understanding the basics of how Craft routes requests is helpful as well.


How do I query data using the Element API Plugin based on a custom field?

You’re close. But the relatedTo param can’t just be set to some username. It has to either be an element ID or an actual element model (more specifically, a user ID or UserModel in this case).

'users/<username:{handle}>/offers.json' => function($username) {
    // Get the actual user model
    $criteria = craft()->elements->getCriteria('User');
    $criteria->username = $username;
    $user = $criteria->first();

    // If there was no user, return no results
    if (!$user) {
        return [
            'elementType' => 'Entry',
            'criteria' => ['id' => false],
        ];
    }

    return [
        'elementType' => 'Entry',
        'criteria' => [
            'section' => 'specialOffers',
            'relatedTo' => ['targetElement' => $user]
        ],
        // ...
    ];
},


Straight Up Craft has a solid list of plugins.

Nice time is most likely the one you are looking for.

http://straightupcraft.com/craft-plugins/nice-time


Disable Stripe email notifications from Commerce

You shouldn't need to adjust Craft Commerce at all. You can disable email receipts on the Stripe side in your account settings.

Account Settings > Emails

Uncheck "Email Customers for: Successful Payments"

As far as Stripe using the previous email address saved with the Customer, as far as I know OmniPay (which powers Commerce) doesn't create a Customer in Stripe, it only creates a Charge.


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

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

These should probably be:

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

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


Sounds like the Always Validate plugin does what you're looking for.


Plugin Installation Error in Craft 3 / PHP Version

Usually when you see that error, Craft was composer install/update'd on one environment with say, PHP 7.2.  Composer then pulls in the highest supported dependencies for that environment.

The composer.lock file is pushed to a different environment with say, PHP 7.1, creating a conflict the next time Composer needs to run.

You can do this to force Composer to use the lowest common denominator for all of your environments: https://github.com/craftcms/craft/blob/master/composer.json#L34-L36


Looping through a Matrix field is pretty easy, here is an example. Also read the docs on the Matrix field here - https://craftcms.com/docs/matrix-fields

{% for block in entry.myMatrix %}
    {% set handle = block.type.handle %} {# Grab the current block handle #}

    {{ handle }} {# Echo out the handle #}

    {% if handle == 'myMatrixBlock' %}
        {{ myMatrixBlock.heading }}  {# If you have a field called heading in myMatrixBlock #}
    {% endif %}

{% endfor %}

Updated

Take a look at these examples...

getting fields of a section (getFields())

How to loop through matrix block fields and pull out handle and content?


How to toggle main product image from multiple images

Something like this (untested):

{% set relatedAssets = product.productPhoto.all() %}
{% if relatedAssets|length %}

    {% for rel in relatedAssets %}

    {% endfor %}

{% endif %}


Probably the name of the folder isn't the plugin handle. Check inside the plugin's folder to see if the actual plugin folder is inside there. For instance:

forge@nys-production ~/nystudio107.com/craft/plugins (master) $ tree -L 1 craft-typogrify/
craft-typogrify/
├── readme.md
└── typogrify

In this case, when the plugin is downloaded or cloned, the name of the folder is craft-typogrify but the actual plugin folder is inside of this folder, and is named as a lowercase version of the plugin handle: typogrify.

This is what needs to be directly in the craft/plugins folder for Craft to see it.


Yes craft provides many tools that allows public registration and editing the profiles without a single line of php or even a plugin. Most functions are covered by the cms and even custom functions like social media support is really easy since you can extend the UserController and change the things you need.

You have the ability to create dynamic user groups, give permissions to those and restrict content on the site via twig. Like with entries you can define a field layout for every user so you could create all the fields you can create in a normal entry and give users the ability to change them in a frontend form

You have config variables and settings that allows you to send custom invitation mails and validation mails.

But you need the commercial version for this. It's not provided in the free one.


Something like this should work:

{% set myStation = getCookie('myStation') %}
{% set relatedStation = craft.entries.id(myStation) %}

{% set params = { section: 'blog', limit: 6, offset: 1, relatedTo: relatedStation } %}

{% if category is defined %}
    {% set params = params|merge({relatedTo: ['and',
        { element: relatedStation },
        { element: category }
    ]}) %}
{% endif %}

{% set entries = craft.entries(params) %}
{% paginate entries as pageInfo, pageEntries %}

The trick with merge is that it will always replace matching keys that it finds.  So you need to tell it to replace it with the proper and syntax.


The simple way to do this would be to log a message to your Plugin's custom log using

ExamplePlugin::log( 'TaskName has completed' );

This would require the user to visit the log and refresh to see if the task had completed - not ideal!

However, if you wanted something that updated as the task was being run you could possibly redirect them to a Plugin template with a text area that  displays a log for the task where you could show completion of each step of the task and then finally a "Completed Task" message.

// Create task
$task = craft()->tasks->createTask( 'TaskName', 'desc' ), array(
  'products' => $products
));

// Set session notice for start
craft()->userSession->setNotice(Craft::t('Import process started.'));

// Redirect to Plugin template page that displays a log
$this->redirect( 'templateName?task=' . $task->id );

Then inside the task you could log messages to be displayed in that template

if($step === $this->getTotalSteps()-1) {
  Log::message( 'Task finished.' );
}


Is there any way to set enable by default a permission on the registerUserPermissions hook?

There's not a native way to do this, but you might want to consider adding it as a feature request.

In the meantime, you might be able to work around it a bit with some custom JS in the control panel and using something like the Control Panel JS plugin.


How can I determine if a user is logged in, and who that user is?

To determine if the user is logged in at all, you'll want to use the currentUser variable:

{% if currentUser %}
    Welcome, {{ currentUser.friendlyName }}!
{% endif %}

To determine if the logged in user is a specific user, then simply compare against their username:

{% if currentUser and currentUser.username is 'johndoe' %}
    Hey Johnny Boy!
{% endif %}

The isCurrent method is useful when targeting a more generic UserModel (where you don't know if the user would be the current user).

{% for user in craft.users %}
    {% if user.isCurrent %}
        {{ user.friendlyName }} is you!
    {% else %}
        {{ user.friendlyName }} is someone else.
    {% endif %}
{% endfor %}


Is it possible to use same template for index and archive template?

The way I do this is to use a different template for each set of entries. So there would be an archive one for all the articles from a given month: _news/index-archive, and a category one for all the articles in a given category: _news/index-category, and one for all of the entries: _news/index-all, maybe one for articles by tag, etc.

Each of these templates sets entries to the relevant entries, and then does

{% include '_news/index-generic' with {
  entries: entries
} only %}

And index-generic has all the shared display code.

Probably there will be a couple of other things that vary as well, for example a heading:

{% include '_news/index-generic' with {
  entries: entries,
  heading: 'Category: '~category.title
} only %}


Dynamic fields layout based on categories

So I'm going to add this as an answer just in case others find it a useful option to pursue.

I would create your fields; voltage, flow rate, etc. then I would create a Structure called Products with different Entry Types corresponding to the various categories you are using to sort your products. Then you can add your fields to the appropriate Entry Types. Then when you go to add a new product, you'll have a dropdown where you can select what Entry Type this entry should be.

That's how I would setup your site structure if I were in your place


Redactor upload image and file does not work

Craft's default Redactor implementation comes with image selection and uploading out-of-the-box that ties to its Assets sources.

If you click this button:

You'll get a modal where you can select already uploaded Assets or upload new ones.


Is it possible to hide certain entries in the Content SEO section of SEO Matic?

A Section only appear in Content SEO if it has public URLs. If it has public URLs, that means that Google and users will be able to find it eventually.

There is a setting to disable the sitemap for a section via Content SEO, however.

Can you elaborate on what you're trying to accomplish?

Also we got into detail on sitemaps for a while on the devMode.fm episode SEO for Web Developers: The Silence of the Chickens which might be useful to you.


Plugin development - How to access actions?

I'd suggest generating the code via pluginfactory.io and if you have code comments enabled, it'll give you the URI that you need to trigger your action in the example code.
But essentially it's going to be a kebab-case version of your controller route, with a kebab-case version of your method name (but removing the action preface).
For you, first you should rename your method thusly:
    public function actionBuu() {
        echo "tradada";
    }

And then your URI would be something like:
/actions/dns-notifier/dns-notifier-controller-db-controller/buu

See here for more on controller actions


Got 404 on login attempt (Template not found: actions/users/login)

Never too late to answer (but fixed weeks ago), apparently our host performed an update on the server that activated several new mod_security rules. One of them was affecting the login.


Moving from Rackspace cloud files to Amazon S3

I would recommend not drag-n-dropping inside Craft. It might end up being very intense indeed, and break down in multiple ways.

A better way would be to download the media locally, replicating the folder structure and files in the S3 bucket, and then manually changing the source id of the Asset / Folders in question in the database.

For concurrent uploading, take a look at s4cmd.


Is there a way to check if a value exists in an array in twig?

Like you said, to test if a value exists in a Twig array you'd do:

{% if myValue in ['apples', 'oranges'] %}
    {# do something... #}
{% endif %}

To check whether the value is an array or object you could use the iterable test:

{% if myValue is iterable %}
    {# myValue is an array or object #}
{% else %}
    {# myValue is probably a string #}
{% endif %}

To be certain, you might be best coming out of Twig using a plugin Template Variable and doing it directly in PHP.


This isn't really an answer, but my investigating was too long for a comment.
Ultimately, craft.app.request.url gets routed through Yii's resolveRequestUri() and likely gets pulled from $_SERVER['REQUEST_URI'].
Anything coming from $_SERVER['REQUEST_URI'] is always going to be URL encoded so using this in a template:

I get this URL encoded output in a browser:

Unfortunately, Twig doesn't have a |url_decode filter, so you'd need to write a quick custom Twig filter that uses PHP's urldecode() method.
But it actually looks like you're having a character encoding issue first because of the ���� and I'm not exactly sure what's causing that.
My guess is its environment configuration related (I'm using https://getnitro.sh in a fairly default setup for testing).


Does Craft/Twig help with cache-busting js/css?

No, Craft/Twig itself doesn't really do anything in regards to cache busting your assets. Bust is one tool, and you'd also want to take a look at the awesome Minimee plugin port.


Content / fields of newly created single don't show up

I was having a similar issue and found a solution that worked for my setup:  https://craftcms.stackexchange.com/a/9016/831


Unfortunately, Printmaker must regenerate the PDF on every save... It can’t simply check to see whether a certain PDF file already exists, because the underlying content or template may have changed that PDF was last generated. You can use Craft's template caching to capture PDF URLs/filenames, to avoid unnecessarily generating the PDF if you know the underlying content hasn't changed.
You can use Google Fonts (or any other external web font) by linking an external stylesheet, or by including the @font-face directive in your inline styles.
Printmaker saves PDF to files in a cache directory that you specify, but it doesn't create or update an Asset element. You could write a custom plugin to do that, leveraging Printmaker's API. Alternatively, you can commission Top Shelf Craft to develop the functionality you need.

Feel free to write support@topshelfcraft.com or post additional questions here on SE if I can be of further help!


How to set cookie to only show intro animation once per session

You could try something like

  {% set vidAlreadyPlayed = getSecureCookie('intro-animation') %}
        {% if not vidAlreadyPlayed %}
            {{ setSecureCookie('intro-animation', 'hey', now | date_modify("+60 seconds").timestamp ) }}

No cookie set

        {% else %}

Cookie set already

        {% endif %}


hacksaw plugin - displaying first 100 characters

In my opinion, the first thing you should do is remove all HTML tags. It's not just paragraph tags which could cause you problems... what about <strong>, <a> or <img> tags which get cut off?

For legibility sake, let's also break this down into multiple steps:

{% set textBlock = entry.bodyContent.type('text').first() %}
{% set plainText = textBlock.text|striptags %}
{% set sumtext   = plainText|hacksaw(chars='100', append='...') %}

And finally, if you do want your text wrapped in a paragraph tag, just reapply that when you output it:

<p>{{ sumtext }}</p>

Since you mentioned having an issue with two paragraphs getting mushed together, let me address that too... You'll want to make use of the Craft replace filter, which can handle regex.

Couple of ways you could tackle that:

{% set plainText = plainText|replace('/\. */', '. ') %} (ensures periods are followed by a single space)
{% set textBlock = textBlock|replace('/<\/p> *<p>/', ' ') %} (gracefully combines paragraphs with a space in between)


With Matrix blocks how can i get the column names

My guess is the array is empty because there is no content.
Try $o_matrix_block->getType()->getFields();


Get and Set existing matrix field data in a plugin

Since Matrix blocks are elements as well it's the same

Your form could be

{% set movies = entry.movies.all() %}
{% for movie in movies %}
    <form>
        <input type="hidden" value="plugin/controller/function" name="action">
        {{ csrfInput() }}
        <input type="hidden" value="{{ movie.id }}" name="id">
        <input type="submit" value="Vote this movie">
    </form>
{% endfor %}

And your controller

public function actionSave(){
    $id = Craft::$app->getRequest()->getRequiredBodyParam('id');
    $matrixBlock = Craft::$app->getMatrix()->getBlockById($id);
    if($matrixBlock === null){
        throw new ElementNotFoundException('Could not find Block with ID ' . $id);
    }

    $matrixBlock->setFieldValue('votes', $matrixBlock->getFieldValue('votes')+1);
    if(!Craft::$app->getElements()->saveElement($matrixBlock)){
        // handle an error
    }

    return $this->redirectToPostedUrl();
}


Can I select the latest draft of a given entry?

Something like this should work:

{% if craft.request.getParam('draft') == true %}
    {% set drafts = craft.entryRevisions.getDraftsByEntryId(entry.id) %}
    {% if drafts|length %}
        {% set entry = drafts[0] %}
    {% endif %}
{% endif %}

{{ entry.title }}
...

This is assuming of course that the entry is published at all. If it's disabled then the uri will return 404. In which case you would have to retrieve the entry in some other way. See this answer for an example.


Reverse the seomatic title and site name for a specific template

The following works (but is undocumented):

{% set seomaticSiteMeta = seomaticSiteMeta | merge({'siteSeoTitlePlacement': 'before'}) %}


Project file changes causing `SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1' for key 'PRIMARY'`

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

This would mean that either:

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


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

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

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


Install button not visible in Plugin Store

Since the Craft install is hosted at Hyperlane, they have a way of locking changes so that you have to push to the repo through git and deploy. No changes can be made to the filesystem through the admin UI.


appId wont help you there. If you take a look at the source code, you'll see how the appId is used in sessions.

I'm not aware of an automatic way to prepend cache keys.


You may have a look at the headless documentation which offers a few solutions / ways such as a GraphQL API, REST-API & a JSON API


Craft Commerce: Checkout without email / address

Commerce is going to require an email address to checkout. It's a required field for a customer.
You could try to "fake" an email address and then try to update it before the order completes (beforeCompleteOrder) after the transaction succeeds, but I think that's more error prone because Commerce has already setup a customer and order details based on that information.
However, you could work around it.
I'm not sure how your payment provider works but on the cart page, you could start the payment process "manually".
Every field is optional - up until you send the order to Commerce Payment model.
You might have a button that says "Login with Provider" or whatever on the cart page. After someone presses that button, behind the scenes, you're calling your own logic.
You might set some fields up for that session including a token to continue the transaction. As far as Commerce is concerned, it hasn't started checkout yet but it feels that way to the customer.
Then after you've grabbed the customer's details and setup the cart, then you can proceed with sending Commerce the details it needs.


How can I sort entries by a custom field in the CP, Craft 3?

Craft 3.2 beta adds support sortable custom fields.


What you do, is this:

Get 30 items from the database, ordered by showTime
Then, you filter them with the if-attribute in the for-statement

This means, that you could get anywhere from 0 to 30 results. What you want to do, is make sure the filtering happens within the element query. I did not test this (not sure about the time criteria part), but something like this should work:

{% for entry in craft.entries
    .section('shows')
    .order('showTime')
    .search('showDay:*' ~ now |date('N') ~ '*')
    .showTime('>= ' ~ now |date('H:i'))
    .limit(3) %}


I had a similar issue - update your composer.json file as per this question:

Composer was unable to install the updates

Alot of additional things may have got added to your composer.json file.


Updating Asset Indexes Fails with TemplatesController Not Found Error in Craft Logs

I would check your server logs for any further clues.


How do I write custom model validators for my plugin that refer to other fields?

Looks like I can just refer to the other field name:

public function validateUsername($attribute)
{
    $value = $this->$attribute;
    $otherFieldsValue = $this->otherField;

    if ($value && strtolower($otherFieldsValue) == 'spartacus') {
        $message = Craft::t("No, I'm Spartcus!");
        $this->addError($attribute, $message);
    }
}


You can use them the same way like you are used to everywhere else. All relation fields extend the same BaseRelationField so their logic is totally equal.

You can either pass an element, an element id or an ElementQuery/ElementCriteriaModel but not a string to the function. If you want to fetch all related elements of an event you'll need to fetch the event first


How can I set new user accounts to pending status in a Craft 3 module?

Yeah you’re correct that db089251 is the culprit here, which fixed a bug where user activation events weren’t getting fired when users were first created, if the “Verify email addresses?” setting was disabled.

Your new code is close, but that is going to get called each time Craft tries to activate a user—both when they are first created, and when you try to manually activate a user later on. So you just need to add a condition to your event handler.

As a starting point, maybe just check if it’s a site (front-end) request.

Event::on(
    Users::class,
    Users::EVENT_BEFORE_ACTIVATE_USER,
    function (UserEvent $event) {
        if (Craft::$app->request->getIsSiteRequest()) {
            $event->isValid = false;
        }
    }
);


Translated pages load a white empty page on localised site

I found this:

I only copied the lines

// Path to your craft/ folder
$craftPath = '../../craft';

// Tell Craft to serve the German content
define('CRAFT_LOCALE', 'de');

// Do not edit below this line
// ...

from the example here: https://craftcms.com/docs/localization-guide to the index.php file in the localised folder.

I did not copy the $path lines from the original index.php file in the webroot. This way I got the white empty pages.

Thanks a lot for the help on Twitter. I'm on my way to finish my first site!


Can I capture the users intent ('Save' vs 'Save and continue editing') for craft()->on('entries.saveEntry'

The 4th parameter to HttpRequestService->sendFile() is $terminate = true, which will by default, terminate the request after the file is sent.

Set that to false and let the request continue as usual and you should be set.


How to set hero image for root and children in a structure

Something like this should do the trick (obviously, change navStructureHandle and entriesFieldHandle to real values):

{# Get the related nav entry for the current entry being viewed #}
{% set navEntry = craft.entries.section('navStructureHandle').relatedTo({
    targetElement: entry,
    field: 'entriesFieldHandle'
}).first() %}

{# Get the root (top level parent) structure entry for the nav entry #}
{% set rootEntry = navEntry ? craft.entries.ancestorOf(navEntry).level(1).first() : null %}

{# If a root entry was found, print out the title #}
{% if rootEntry %}
    {{ rootEntry.title }}
{% endif %}

With the above, rootEntry will be null if the current entry doesn't have a related nav structure entry, or if a top level parent can't be found for the nav entry (i.e. the nav entry is top level).

I wouldn't worry too much about the performance with the above, but if you do feel it's too complex for printing a header, you could consider using the Preparse plugin instead. Preparse basically lets you create a custom field containing Twig code that will be parsed whenever the entry is saved. This basically lets you "cache" the result of costly Twig operations to a plain text, custom field on an actual entry.

Using Preparse, you could add a field called navHeaderTitle to your child entries (i.e. not the nav section). The field should contain the Twig code above, in addition to actually printing out the rootEntry title if a root entry is found (note that it's a good idea to wrap the whole thing in a {% spaceless %} tag pair):

{% spaceless %}
    {% set navEntry = craft.entries.section('navStructureHandle').relatedTo({
    targetElement: entry,
    field: 'entriesFieldHandle'
}).first() %}
    {% set rootEntry = navEntry ? craft.entries.ancestorOf(navEntry).level(1).first() : null %}
    {{ rootEntry ? rootEntry.title }}
{% endspaceless %}

Then, you could simply do something like this in your template:

{# No need to pull any entries; just test for the `navHeaderTitle` field #}
{% if entry.navHeaderTitle %}
    {{ entry.navHeaderTitle }}
{% endif %}

Of course, the caveat with the Preparse approach is that if you ever change your root entry's title, you'll have to re-save all your child entries in order to re-parse the Twig and update the entries' navHeaderTitle value.

A good compromise could be to use Preparse, but echo out the root entry ID instead of the title – then you could do this in your template:

{% set rootEntry = entry.navHeaderEntryId ? craft.entries.id(entry.navHeaderEntryId).first() : null %}
{% if rootEntry %}
    {{ rootEntry.title }}
{% endif %}


Order entries by "recently modified" date time in control panel

Short answer is, you can't.

Long answer... Ian has some good advice, but the Post Date won't update automatically. Your best solution would be to update the Post Date every time you update something else in the entry. Then your Post Date will essentially represent your "last changed" date.

Bonus answer... If/when you do build your own plugin, you can look into building your own Element Type. (Just a fair warning... building a custom Element Type is a little more advanced.) When you're setting up your Element Type, you can define which columns appear in that "list" view. One of the native columns in every Craft DB table is "dateUpdated", which contains exactly the information you're looking for. Just output that as one of your columns, and voila!

There's no rush, I can wait answer... the ability to add custom, sortable columns to the entries (and users, assets, etc.) index pages is coming “Real Soon Now”™.


How can I limit a list based on a custom date field

Actually you should be able to specify your custom field as part of the chained element criteria:

{% set currentAndFutureEvents = craft.entries.section('events').eventDate('>= ' ~ now).order('eventDate DESC') %}

Source: https://plus.google.com/111247306448293182882/posts/Uu6ZuTH1NBu


Generate previews of PDF files (Craft 3)

I created a plugin specifically to do this -
https://github.com/bymayo/craft-pdf-transform

It takes Asset PDF files and coverts them to JPEG / PNG files automatically when they are uploaded.

Or, do theres a Twig method that lets you convert the PDF to an image if the image already exists in Assets. But this can be a bit labour intensive on the server to do when a template is rendering so is only advised for small files.


Search in checkbox field with pagination

The value is stored as a serialized array in your database,  you would need to filter for the string "["healthcare","food-fitness"]"

Since your query parameter is an array you just need to prepend an and parameter to it so it looks like

articles_categories(['and',  '*healthcare*', '*food-fitness*'])

If you have only one parameter and want an exact match you need to search for the exact string

craft.entries.articles_categories('["healthcare"]')


Asset fields return like an array so they can potentially have more than one item, you need to request the first item only with .one() (as opposed to requesting .all())
//First check if the asset field has more than zero items
{% if block.video.videoFileWebm|length %}
    // Retrieve the first and only item in the asset field
    <source src="{{ block.video.videoFileWebm.one().url }}" type="video/webm">
{% endif %}

I would also set block.video to a variable to clean up the code a bit and maybe speed it up a little.


Entry element query missing user field data when user is suspended

User queries by default will only return active users, not pending or suspended ones.

To include suspended users, change this line:

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

to this:

$user = $entry->user->status(['active', 'suspended'])->one();

Or if you want to include pending users as well (users who haven’t activated their account yet), you can do this:

$user = $entry->user->anyStatus()->one();


multi language - each in its own folder?

"there is no 'tab' above an wysiwyg field under the very same article where i can switch between languages and fill in the corresponding content on the very same admin-page, right?"

Actually, there is (sort of). It's not a tab per se, but you can switch between the different versions of each entry as you are editing them.

So you would add all of your entries in English first, then circle back and adjust the content for each entry in German.

And as you mentioned, there is a Site Switcher plugin (disclaimer, I am the author) to let you easily switch between languages while staying on the same page.


Cannot connect to database with credentials provided in db.php

Move the check the SERVER_NAME switch up above the require_once $path;. You need to set CRAFT_ENVIRONMENT earlier.


You can call it from the front-end, but it requires the currently logged in user to be an administrator.

Just point the form's hidden action input to users/impersonate and have it submit a 'userId' input of the person you want to log in as.


How to fetch entries based on contents of several custom fields?

No, but this is possible with a few lines of plugin code. You just need to create a DbCommand object from your criteria model and add your WHERE conditions with a OR operator.

Add this function to your Template variable class and you can get the entries from your templates with a single query.

public function getEntriesWithVars($vars)
{
    $criteria = craft()->elements->getCriteria(ElementType::Entry);
    $criteria->section = 'sectionName';
    $criteria->limit = null;

    $query = craft()->elements->buildElementsQuery($criteria);

    $conditions = array(
        'or',
        array('in', 'field_customField1', $vars),
        array('in', 'field_customField2', $vars)
    );

    $query->andWhere($conditions);

    $results = $query->queryAll();

    return EntryModel::populateModels($results);
}

{% set vars = ['foo', 'bar'] %}
{% set entries = craft.myPlugin.getEntriesWithVars(vars) %}


Iterate through all rows of specific page using Freeform?

Or I could actually read all the documentation: Method getRows()

As in {% for row in page.getRows() %}


How to render a Twig template in the element-api plugin (v2.5)

You didn’t tell where that Twig file is located, but I assume your issue has to do with being in the wrong “Template Mode”.

Here’s how you can switch mode:

Craft::$app->view->setTemplateMode()

Documentation: https://docs.craftcms.com/v3/extend/updating-plugins.html#rendering-plugin-templates-on-front-end-requests


Creating partials outside of the templates folder

So a few potential things to consider:

You do not want to be serving static assets like Javascript, CSS, etc. out of the templates directory.  I realize you're planning to put them "elsewhere", but ensure that elsewhere is in the /public/ folder, so that php, Yii, and Craft do not have to be spun up just to serve a static asset.  Do not use a Craft routine/plugin to load them.
The entire point of modularization is that the payoff is down the road as you're able to reuse components on future projects by just "plugging them in".  I've seen this approach taken on many types of software projects, from desktop apps to mobile apps to websites.  It almost never works out as well as people think it will, unless it is seriously well architected, because we're generally not a factory churning out widgets.  There are things unique to each website beyond the basic functionality that requires customization; writing something that is both that general, and also useful is difficult.  Think of how many hours you have spent fighting even well-implemented frameworks like Bootstrap or Foundation.
Most things of this nature either end up being way, way over engineered and bloated, with a ton of time spent on them, and the promised gains down the road in terms of time savings never being realized due to the aforementioned issues.

Just my two cents.


Compare custom-field value of entry to registration-form field value before saving user

Thanks to Brad Bell, I was able to troubleshoot using var_dump. The code above works correctly, but I'm unaware of how to do a simple validation of the code within the controller, w/o creating a new model, & send back a response.

Instead (for simplicity on my end), when the validation fails, I redirected to an error specific page, referencing the code entered & team name.


How should we be setting up product categories/sub-categories?

There's a lot of different ways to set up your store structure but categories in Craft are like folders you put stuff in. Entries/products are what goes into those categories.

Category Groups

The most basic way to set it up would be to create a new category group inside Craft and then start creating categories.  Category groups are like the filing cabinets you use to put the folders in.

You can make as many category groups as you need and they'll show up separately in the sidebar. If you only have a few categories you can usually get away with one category group but it can also depend on how you want users to search and filter on your store.

Sub Categories

Categories can also contain subcategories. To put Dogs underneath your Pets sub-category grouping, just drag it underneath after it's created). It'll start looking like the hierarchy you want in no time.

To get the categories relating back to products, you'll want to create a new category field that you'll use on the product (or variant). That will allow you to relate products back to categories and be able to search on them.

Product Types

Depending on how your store is setup, you may want to create different product types as well.

Like Category Groups, Product types are one of my favorite features in Commerce and can be very useful if your store sells different types of products that need different sets of fields/options for each. It's especially handy if your ordering process is going to be different for each product type.

It's also useful especially if you sell thousands of products; seeing pet stuff and fashion stuff in the same part of the control panel area can get confusing quickly.

In your case, I'd probably create another product type just for events since it's going to be very different than the physical products you sell.

Hope that gets the ball rolling...


How to create a category filter for a portfolio site?

The site you linked to is using Isotope to achieve this effect. Isotope is simply a JavaScript filtering library - it's all front-end so really this has nothing to do with Craft, unless you want to load entries dynamically via AJAX.

(Most Isotope implementations I've seen simply load everything and then hide/show the relevant ones when clicking on filters... It depends how many items you have as to whether it's worth loading them in dynamically, but it's a lot simpler to load everything in one go).


Does a programmer have to creates meta tags? I'm the end user (not a programmer)

Metadata is an important part of a website. If you are getting poor scores from website graders and don't see any place on your site to add that information it likely wasn't implemented by the team that built your site.

It's good you've noticed this and it's worth taking the time to set up a way to manage the metadata on your site. The best way to do this in a comprehensive and maintainable way is with an SEO plugin. Once you have things setup, you should no longer need the assistance of a programmer to manage the majority of your SEO needs.

For Craft, at this point in time, there are two good SEO options that are very comprehensive in the types of metadata they manage:

Sprout SEO
SEOmatic

My firm is behind Sprout SEO, so my preference is with it, but SEOmatic is made by a respectable developer who I would recommend as well so it's really a matter of your preference on which one works best for you.

With either plugin, once you have it setup, you can focus on your content and the SEO plugins will worry about generating and outputting the metadata you need on your pages. If you decide to refine or grow your SEO strategy, both plugins also have ways to give you additional control over customizing the metadata further, but that's probably something that can be left for another time in your case.

Leveraging a plugin, it will likely take a developer 2-4 hours to implement a good SEO baseline on your site. For a custom or more advanced implementation, additional planning and implementation will be required.

Please take this estimate with a grain of salt as every custom website is unique and if your original developer didn't set up any metadata that could be a signal that the rest of the project also has some non-standard things in the setup that would take the next developer more time to figure out. If you have a large site or advanced content, it can also take longer to customize metadata for special considerations, specialized content types, or your particular goals.


You need to create several inputs and apply them to your topics category group.

Description field
Assets field for PDF's
Matrix field that allows the user to add multiple FAQ's

In your Services detail page get the category from your category input and output the description:

{% set topic =  entry.categoryInputHandle.first() %}
{{ topic.descriptionFieldHandle }}

Next in your Resources detail page grab the category and output the PDF and FAQ's.

{% set topic =  entry.categoryInputHandle.first() %}
PDF
{% for faq in topic.faqMatrixFieldHandle %}
    {# output the different fields you setup in the matrix… #}
{% endfor %}


How do you set up live preview for headless Craft CMS installs connected to Gatsby?

When you enter live preview in the cp, it's an iframe to the URL you've set up for that section, including a token=xxxxxxxx, you need to pass this along to your GraphQL (assuming that's what you use), to let it know it's not supposed to fetch data from the database.

Andrew Welch has a bit more info about it here: https://nystudio107.com/blog/headless-preview-in-craft-cms

As well as another question here (based on vue, so you probably need to change som stuff for Gatsby): Live preview using Vue.js


Just a quick guess, but here is what I have on a project I am working on.

$client = new \Guzzle\Http\Client();
$request = $client->get($url);

yours

$client = new \GuzzleHttp\Client();

mine

$client = new \Guzzle\Http\Client();

I have \Http\Client - maybe you are just missing the slash?


Is it possible to change admin Actions URL (not only the URI)

ok, just received the answer from the support. will add it here for anyone who has the same issue:

setting the baseCpUrl in the config/general.php does the trick:

'baseCpUrl' => 'https://cms.example.com/',


How to redirect with error messages?

Generally speaking, then answer is "you don't".  You redirect on success, but if there is an error (validation or otherwise), you add those to your model, call setRouteVariables and let the request continue as usual.  That will reload the current page and you can pull the errors out of the model from Twig.

You can see the general workflow for this in a controller action in all of Craft's controllers at craft/app/controllers.

class SomeController extends BaseController
{
    public function actionDoSomething()
    {
        $myModel = new MyModel();
        $myModel->myProperty = 1;

        // Validate the model
        if ($myModel->validate())
        {
            // Pass it to the service.
            if (craft()->myService->doSomething($myModel))
            {
                // Success!
                $this->redirectToPostedUrl();
            }
        }

        // Return the model back to the template so the errors can be displayed.
        craft()->urlManager->setRouteVariables(array(
            'model' => $myModel
        ));
    }
}


Commerce: How can I check that a user has bought a product?

There is a direct way to find this out.
Here's an example.  Note the id you supply must be the specific purchasableId, not the product id (so the defaultVariant.id or variant.id).
{# Has the customer explicitly bought the XXX product? Returns 0 (==false) or >= 1 (==true) #}

{% set purchasedXXX = craft.orders()
    .user(currentUser)
    .hasPurchasables(10637)
    .isCompleted()
    .count()
%}

You can then use that as just
{% if purchasedXXX %}
 ...
{% endif %}


Uploading Lottie animation files with images

How are the images included in the json-file? Do you need upload the images as well? I assume, that you do have a problem with the image paths? Please describe your workflow and folder structure.

Frontend-Side you could always replace some strings via twig. In your case you could replace a path-segment from the json field.


Generate PDF preview images automatically?

There a plugin for that:

https://github.com/carnesmedia/pthumb

PThumb is a Craft plugin that generates thumbnail preview images for PDF documents. It's easy to drop into your templates, requires only the commmand-line version of ImageMagick (not the PHP bindings), and caches the generated thumbnails.


How can I pass a JS result into a Twig template?

Per Michael's suggestion above, with some help from this answer, I passed the results from the API call back to a craft template as query params, so it looked like this (simplified):

{% if craft.request.isAjax %}
    {% set myReps = craft.request.getParam('personId') %}
    {% set myIds = myReps | split(',') %}
    {% for myId in myIds %}
        {% set person = craft.entries.section('representatives').repId(myId).first() %}
    {% endfor %}
{% endif %}

and then output my info from there.


The Super Table field value is a query, so the .all() needs to be called on the field itself (not on lightswitch). But looping over queries is in itself deprecated in Craft, so you should set it to a variable first, and then loop over that.

In any case, the .all() will return all rows of your Super Table field, each of which contains your lightswitch field (even if there is only one row).

If you know there is only one row, perhaps something like this would work, but I haven't tested it:

{% if craft.products.supertable.one().lightswitch == 1 %}

I would anyways recommend performing the query first, then use the result to loop or get your field.


Craft has the ability to dynamically add subfolder paths to Assets when you are creating the Asset field in the control panel.

Tags like {slug} and {author.username} are some of the available options for creating the directories.

I know it has been brought up before and they have acknowledged the possibility. So who knows, maybe we will see it in 2.2?

For now, if organization is a concern I recommend using subfolders to keep it clean.


Email template variables not rendering from plugin

The above template path code works fine. I was just looking for a user variable that hadn't yet been set


How to update stock on a product variant? Setting unknown property error

Have figured it out. Need to:

use craft\commerce\elements\Variant; // not Product
setFieldValue still does not find variable stock with Variant, but set it using $variantEntry->stock = 20;
Need to find() on Variant to return the actual variant, and not
find product with variant as that returns the product

Following works, changed $productEntry to $variantEntry
use Craft;
use craft\web\Controller;
use craft\helpers\ElementHelper;
use craft\commerce\elements\Variant;

$variantEntry = Variant::find()->sku('mysku')->first();
if($variantEntry)
{
    if (!$variantEntry->hasUnlimitedStock)
    {
        $variantEntry->stock = 20;
        echo Craft::$app->elements->saveElement($variantEntry);
    }
}


How do you handle complex navigation in Craft?

If the {% nav %} tag doesn't give you enough control over the output, you can always replicate the behavior with custom loops and the getChildren() method. Just nest them as far as your navigation hierarchy possibly gets.

Edit:

Here an example code on how you'd dynamically call getChildren() on each top-level entry of your structure. If you need to go deeper another level in the structure's hierarchy, I marked the line where you would do that:

    {# Get top-level entries in pages structure (exclude home page)  #}
    {% set pages = craft.entries.section('pages').id('not 1').level(1) %}

    {# Loop through top-level entries #}
    {% for page in pages %}

        {# Check if entry has descendants #}
        {% if not page.hasDescendants %}

            {# List navigation item if entry has NO child entries #}

                {{ page.title }}

        {% else %}

            {# List navigation item if entry does have child entries #}

                {{ page.title }}

                    {# Get child entries of current iteration's top-level entry #}
                    {% set subPages = page.getChildren() %}

                    {# Loop through those 2nd-level entries #}
                    {% for subPage in subPages %}

                        {# This is the place where you'd nest the next menu hierarchy !! #}

                        {# List sub-menu navigation item #}

                            {{ subPage.title }}

                    {% endfor %}

        {% endif %}
    {% endfor %}

.

Because most of your question's topics are already covered by other Q/As, I'd also recommend you to read through these too.

How to realize a client editable navigation:

Would you use a Structure as navigation over multiple sections?
How to build a great multi-lingual navigation witch channels, structure, and manageable in the CP
Multi-lingual site navigation made of singles, channels and structure
Add home page to a stucture?

More control over the HTML output of the nav tag:

Custom or complex nav tag


Troubleshooting paginated content cached globally

I ran into this today. I thought craft.request.path used to include the pagination page number but it doesn't appear to anymore. Maybe it was always like this though.

Regardless, this is how I'm now handling it:

{% cache globally using key craft.request.path ~ '/p' ~ craft.request.getPageNum %}
...
{% endcache %}


Craft CMS Database Structure and Schema Schematics

Tools like Navicat and MySQL Workbench both have ways of analyzing a database and generate a schema map from it, so you can visualize the tables, foreign keys, etc.


Is it possible to create a fieldtype that creates a many to many relationship between two entry sections?

There's still a few kinks to work out, but I developed a plugin that solves this problem using Craft's native Many to Many relationship that already exists.

Basically, I've created a field type that links the relationship from the other side of things and allows you to add entries to it.

You can find it here:
https://github.com/page-8/craft-manytomany

Thanks @Brandon Kelly for the help and guidance.


Search for entries with matrix field's value

What I've done in a comparable situation is to add a hidden field to that entry type. And then I save Matrix data to that field on every save by listening to onBeforeSaveEntry events.

This makes the access to such processed Matrix data in templates or other parts of your plugin (i.e. getEntryTableAttributeHtml) very easy.

Event handler

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

    if($entry->section['handle'] == 'campaigns')
    {
        $longTravels = false;

        foreach ($entry->travelDates as $travelDate)
        {
            $duration = $travelDate->startDate->diff($travelDate->endDate);

            if ($duration > new DateInterval('P30D') && $duration < new DateInterval('P60D'))
            {
                $longTravels = true;
                break;
            }
        }

        // Set value for hidden field 'longTravels'
        $entry->getContent()->longTravels = $longTravels;
    }
});

CSS for hidden field type

{% set hiddenField %}
    #fields-{{ id }}-field {
        display: none;
    }
{% endset %}

{% includeCss hiddenField %}


German special characters like umlauts (ä, ö, ü) are not converted correctly with convertFilenamesToAscii

This was a bug and has now been fixed in Craft 3.5.12.1
https://github.com/craftcms/cms/issues/6923