Adding dynamic second email address to Contact Form plugin

Both, the example from the Contact Form docs

{{ 'me@example.com,me2@example.com'|hash }}

...and the 3rd example snippet in your question

{% set firstEmail = 'me@example.com' %}
{% set emails = firstEmail ~ ',me2@example.com' %}

{{ emails|hash }}

...output exactly the same string for me! So I think you have to search for an answer to your issue elsewhere.


How can I specify order when getting all products of a given type?

As an element, it has the same order criteria as entries, assets, &c. So you should have no problem using order('defaultPrice') in your criteria. That's for price low-to-high. For high-to-low, you add desc to the criteria. So: order('defaultPrice desc').


I figured out what was happening. There was a conflict with a previously installed plugin, Sprout Invisible Captcha.


Can a plugin add JS or CSS to the control panel in Craft 3?

You should be able to do this with Asset Bundles. Full documentation on this is here.


Set user based on their attachment to a product

{% set user = product.usersFieldHandle.first() %} will give you the UserModel of the first related user.

Then e.g. {{ user.fieldHandle }}


Show related entries that have the same Category, and some of the same tags?

If you don't mind using a plugin, Similar would work very well for your use case:

{% set relatedEntries = craft.similar.find({
    element: entry,
    context: entry.tagsField.ids()|merge(entry.blogCategory.ids()),
    criteria: {
        section: 'blog',
        limit: 3
    }
}) %}

Of course, be sure to replace tagsField in the above example with the actual handle for your entry type's Tags field.

By default, the entries returned by Similar will be ordered after the number of relations in common with the current entry (or whatever you pass into the element parameter). In other words, the entry with the most tags and/or categories in common with the current entry will be the first. The entries returned by Similar will also have an entry.count attribute that will indicate the number of relations in common with the current entry.

If you want to do this without a plugin, it's possible to add multiple criteria to the relatedTo parameter in order to pull entries that has either one or more categories or tags in common with the current entry:

{% set relatedEntries = craft.entries({
    section: 'blog',
    relatedTo: ['or', {
        targetElement: entry.blogCategory.ids(),
        field: 'blogCategory'
    }, {
        targetElement: entry.tagsField.ids(),
        field: 'tagsField'
    }],
    id: 'not ' ~ entry.id,
    limit: 3
}) %}

I'm not aware of a way to query the EntriesService for the 3 entries with the most relations in common with entry, though (the lack of such a feature is why the Similar plugin exists). I guess this could be achieved in plain Twig by possibly setting the limit parameter to null (to return all entries – yikes! performance), looping over the returned entries and comparing the number of relations in entry.tagsField and entry.blogCategory to each related entry and add the entries to an array ordered by the amount of relations somehow, but I suspect it will get pretty dirty and quickly go beyond what Twig is designed to comfortably do, logic-wise.


How to save a new entry with custom fields - Craft 3

It turns out the data wasn't being saved as I hadn't set a fieldLayoutId value.

Now that I've figured this out, I've written a helper method to make saving any entry type much easier:

public static function saveNewEntry(string $handle, array $fields) {

    $entryType = EntryType::find()->where(['handle' => $handle])->one();

    $entry = new Entry();
    $entry->sectionId = $entryType->getAttribute('sectionId');
    $entry->typeId = $entryType->getAttribute('id');
    $entry->fieldLayoutId = $entryType->getAttribute('fieldLayoutId');
    $entry->authorId = 1;

    if(isset($fields['title'])) {
        $entry->title = $fields['title'];
        unset($fields['title']);
    }

    if(isset($fields['slug'])) {
        $entry->slug = $fields['slug'];
        unset($fields['slug']);
    }

    $entry->setFieldValues($fields);

    if(Craft::$app->elements->saveElement($entry)) {
        return $entry;
    } else {
        throw new \Exception("Couldn't save new bespoke product: " . print_r($entry->getErrors(), true));
    }
}

This can be used like so:

return self::saveNewEntry('article', [
    'title' => $id,
    'slug' => $id,
    'excerpt' => $excerpt,
    'body' => $body
]);


Is it possible to validate whether all assets in an entry have been uploaded?

I do not believe there is an easy way to do this with Craft out of the box. Uploading 2k images to an entry is a bit of an edge case. I would recommend uploading all of those images directly to the asset volume.

That being said, you might want to search the plugin store to see if anyone has created a plugin like this. You could also create your own plugin, copy the code for the asset field, and extend to notify when the upload is complete.

Good luck!


How to allow non-admin user group to copy password reset URL and activation URL?

Currently that's the expected behavior.  Feel free to add your voice to this feature request, though: https://github.com/craftcms/cms/issues/942

Of course you could always write a plugin that exposed whatever features you wanted to whomever you wanted bypassing Craft's logic.


Email template issue Craft Contact Form Extensions

I think it should be:

{{ submission.message.Phone }}


ok - just figured it out after reading Brandon's answer here Asset URLs not HTTPS

The missing piece was to set the url setting of the asset source to root relate e.g. /uploads/images

Clear the cache and all sorted!


Read POSTed JSON data from the request body

Yes, you can use getRestParams() like so: $input = craft()->request->getRestParams()

A bit confusing naming there, which is why it's changing to getBodyParams() in Yii 2.


Alphabetical index for a list of entries

First, sort all entries by multiple criteria:

{# get our entries and order by firstname, lastname #}
{% set allEntries = craft.entries.section('entries').orderBy('lastname asc, firstname asc').all() %}

Then use craft's custom "group" filter (lastname[:1] picks the first letter):

{# group them by the first letter of the last name https://docs.craftcms.com/v3/dev/filters.html#group #}
{% set allEntriesByGroup = allEntries | group('lastname[:1]') %}

Then loop through that multidimensional array (firstletter, entriesInGroup) is key -> value in twig:

{% for firstletter, entriesInGroup in allEntriesByGroup %}

{{firstletter}}

    {% for entry in entriesInGroup %}

{{entry.lastname}}, {{entry.firstname}}

    {% endfor %}

{% endfor %}


Pages for each entry from an entry type?

What about using a category group for your designers as well?

Add your "Specialty" and "Locations" category fields to a "Designers" category's field layout and then use a "Designers" category field on your blog entries to assign the designer.

Sorry for the confusion with my other answer, after re-reading your question today I noticed that I headed in the wrong direction. A "Designers" category would probably be the right way to do it, even if you had the ability to add a second channel section.


The "HTML Email Template" option in Settings > Email in the Craft control panel is completely unrelated to the Contact Form plugin.

If you want to change the body of the email that gets sent out, you'll need to write a plugin that listens to the beforeMessageCompile event as documented here: https://github.com/pixelandtonic/ContactForm#the-contactformbeforemessagecompile-event


If I understand this correctly, you can't put the /craft folder above the public root, so you put both /craft and /public inside public root? That's no point, and you need a lot more .htaccess vodoo to get that sorted out. But, if the craft folder has to stay inside the public webroot, you should just move it there, and not have an additional /public folder inside it. Your setup should look like this:

craft
index.php
.htaccess

In your /public/index.php file you the path to craft to $craftPath = './craft'; and use the default .htaccess file that comes with Craft (or a more complex one).


Craft Commerce one time billing address creation

Currently there's not much in the way of back end support for creating customers as such.  You can create craft Users in the back end, but given a commerce customer is not necessarily a Craft user, I think the short answer is no.

You could certainly create front end stuff that effectively achieves this though - how you prep all the form work for addresses is up to you, so you could e.g. force your checkout flow to go through a 'set billing address' page the first time and then simply never offers the opportunity to change that later.

You could even create forms for this part of the process that are only accessible by admin, so that you're creating your own 'back end' interface for this....and then pass off the created customers to your actual customers who then see a checkout that only lets them set the billing address.


How does a plugin include it's own config options?

You can add a config.php file in the root of your plugin's folder (craft/plugins/pluginhandle/config.php) that specifies the default values of your config items by returning an array of key value pairs for config settings and values.

If a user wants to change any of those settings, they can add a pluginhandle.php config file to craft/config/pluginhandle.php that returns an array with the overridden key value pairs.

From your plugin, if you call:

craft()->config->get('key', 'pluginhandle')

then Craft will return the user supplied value, if it exists, and fallback on the plugin supplied default value, if it does not.

Also worth nothing that all of Craft's multi-environment config stuff will work in this context for the plugin, too.


How to get name of template that was chosen for request?

Maybe not the solution you was looking for, but here is an alternative solution I'm using.

Put a Twig block in your "master template" (_layout.html?) like this:

<body class="{% block bodyClass %}{% endblock bodyClass %}">

And from my templates I can add classes to the body tag like this:

{% block bodyClass %}{{ parent() }} news-index anotherclass{% endblock bodyClass %}

Or replace the classes by omitting the parent() like this:

{% block bodyClass %}news-index anotherclass{% endblock bodyClass %}


Your error is in this bit:
        // @var LineItem $lineItem
        $lineItem = $event->lineItem;

Looking at the event in question:
https://craftcms.com/docs/commerce/3.x/events.html#beforecapturetransaction
...this shows that you get a Transaction model supplied in this event:
https://docs.craftcms.com/commerce/api/v3/craft-commerce-models-transaction.html#public-properties
...note that model gives you direct access to the related order element:
https://docs.craftcms.com/commerce/api/v3/craft-commerce-elements-order.html
...from which you can then retrieve all the line items (and products etc associated with them), by looping over order.lineItems


Hiding my plugin table columns for mobile

I have never used it, but there is a method craft.request.isMobileBrowser().

{% if not craft.request.isMobileBrowser() %}
    non-mobile browser column
{% endif %}

or even better, you could give that column a class, and then include a mobile css file to layout the table for mobile:

{% if not craft.request.isMobileBrowser() %}
   {% includeCssFile "/assets/css/mobile.css" %}
{% endif %}


Correct Limit for Entries with IF statements

You can restructure your code in two different ways here. But firstly let's see what's the issue with your current implementation. Currently you always fetch 2 entries with your entry query (assuming you have at least 2 entries in total). After that you even filter them further according to the user login status and the use country. This way you'll always end up with 2 or less entries remaining. What you want is always exactly 2 entries.

A) Build your query with the user country în mind. You may have a switch statement to build a query with the country filter and one without the country filter. If it's hard to bake the country into the entry query you could B) fetch all entries of that section and then filter them down to the country and count you want to have. (This could have performance caveats depending on how many entries you have. You may want to cache the query results. But watch out when caching user specific queries. You have to use unique caching keys otherwise user A could see the content of user B.)

I can't show you an exact implementation of the query with country because it's not totally clear to me what's going on in your sections and fields. You may explain the articlesWhitepapers section further.


How to get data from a Global Set in a plugin?

You can use the GlobalsService service available with craft()->globals like so:

// Get the settings global set
$settings = craft()->globals->getSetByHandle('settings');

// Access the address field
var_dump($settings->address)

Or you could use ElementCriteria as you suggested:

// Get the GlobalSet element critera
$criteria = craft()->elements->getCriteria(ElementType::GlobalSet);
// Set the handle you want
$criteria->handle = 'settings';
// Find the settings set
$settings = $criteria->first();

// Access the address field
var_dump($settings->address)

You can access all fields on the $settings variable using this synthax.

Mario


Does a plugin runs it's migrations on install?

The object of migrations is to provide a way for existing installations of your plugin to get the updated db schema as you update your plugin, without having to uninstall (which would mean they would lose all plugin data) and then reinstall your plugin.

  If your schema changes over the life of your plugin, you can write a migration to keep existing installations updated with the latest schema. Craft automatically checks for new migrations whenever a plugin’s version number changes.

https://craftcms.com/docs/plugins/migrations

This is because when a plugin is installed, Craft/Yii will go through your records and create the needed tables/columns as you have defined.

If a user downloads the updated plugin and replaces the current version, they won't have the new columns and things could break as they navigate and try to add data.

This is where migrations play an important role, they are to prevent existing users having to lose all plugin data by uninstalling and reinstalling, so when you change your plugin version, Craft will see there is an update and run through all the migrations to bring them up to the current version.

This is especially handy if for example someone has version 0.1.0 and they update to version 1.0.0, which could be quite a leap.

So in short, if you add new attributes to your plugin record, they will be added for new installations but migrations are only for existing installations


Plugin settings - file field upload location

Unfortunately, a simple HTML file input on its own isn't enough to upload an image (in Craft or anywhere else) – the input simply exposes the file on your local filesystem to the browser/server. In other words, with your current setup, you're not actually uploading anything.

In my opinion, you have two choices:

Use Assets and Craft's built-in Assets ElementSelect input (easy)
Don't use Assets; upload the image natively using a file input (harder)

Personally, I'd recommend that unless you can't have the image be an Asset file for some reason, you should definitely go with the Assets approach. It's way easier to set up, offers a familiar user experience and you can even use image transforms and whatnot since your myImage file will be a bona fide Asset.

Either way, here's how option 1 could look:

In your plugin's settings.html file, replace your current call to the forms.file() macro with this:

{{ forms.field({
  label: "My Image"
}, include('_includes/forms/elementSelect', myImageSelectConfig)) }}

Then, fire up your plugin's primary class. Revise your getSettingsHtml() method to include the myImageSelectConfig attribute referenced in settings.html above, so the method looks something like this:

public function getSettingsHtml()
{
    return craft()->templates->render('yourpluginhandle/settings', array(
        'settings' => $this->getSettings(),
        'myImageSelectConfig' => array(
            'id'                 => 'myImage',
            'name'               => 'myImage',
            'jsClass'            => 'Craft.AssetSelectInput',
            'elementType'        => new ElementTypeVariable(craft()->elements->getElementType(ElementType::Asset)),
            'elements'           => $this->getSettings()['myImage'] ? craft()->elements->getCriteria(ElementType::Asset, array('id' => $this->getSettings()['myImage'])) : null,
            'sources'            => array('folder:2'),
            'criteria'           => array('kind' => array('image'), 'localeEnabled' => null),
            'limit'              => 1,
            'viewMode'           => 'table',
            'selectionLabel'     => Craft::t('Add image'),
        ),
    ));
}

Note: The sources attribute refers to the ID(s) for the Asset folder the admin should upload images to (and choose images from). You can look at the craft_assetfolders database table to figure out which ID(s) you want. Alternatively you can remove the sources property entirely, to enable all folders – which is probably the best option if this is going to be a publicly available plugin.

And that's it. The actual myImage setting value stored will be an array with the ID to the selected Asset file, e.g. {"myImage":["42"]}. If you need to pull the Asset in a template, you'll need to add a Variable class to your plugin, exposing the plugin settings:

class MyPluginVariable
{
    public function settings()
    {
        return craft()->plugins->getPlugin('myPlugin')->getSettings();
    }
}

...and in your template:

{% set assetId = craft.myPlugin.settings.myImage %}
{% set asset = craft.assets.id(assetId).first() %}

If you don't want to go with the Assets approach, you can keep your forms.file() macro in settings.html. However, there's a few more things you'll need to handle to get the upload working.

First, in order to actually upload a file from a file input, the enclosing form needs to have an enctype="multipart/form-data" attribute. Unfortunately, plugin settings forms don't, and there's no real way to add it. However, you can use jQuery to hack it in – add this to your plugin's settings.html file:

{% includeJs '$("form:first").attr("enctype", "multipart/form-data");' %}

Second, you'll need some server side code to actually handle the upload. Add the following to your plugin's primary class:

public function prepSettings($settings)
{

    $imageFile = UploadedFile::getInstanceByName('settings.myImage');

    if ($imageFile) {

        // Where should the image be stored?
        $basePath = $_SERVER['DOCUMENT_ROOT'];
        $uploadFolder = '/uploads/yourpluginhandle/';
        $filePath = $basePath.$uploadFolder.$imageFile->name;

        // Make sure the upload folder exists
        IOHelper::ensureFolderExists($basePath.$uploadFolder);

        // Attempt to upload the file
        if ($imageFile->saveAs($filePath)) {
            // File uploaded successfully – store the relative filepath in the plugin settings
            $settings['myImage'] = str_replace($basePath, '', $filePath);
        } else {
            // Aw.
            craft()->userSession->setError(Craft::t('Unable to upload image {filename}', array(
                'filename' => $imageFile->name,
            )));
        }
    }

    return $settings;

}

The above example is pretty much the bare minimum you'd need in order to upload a file from your plugin's settings page, to an arbitrary folder on your server's file system. The example prepSettings() script will upload the file to a folder called /uploads/yourpluginhandle in the public webroot (i.e. $_SERVER['DOCUMENT_ROOT']), before storing the relative path to the file in the settings, if the upload was successful.

Keep in mind that file uploading is actually fairly complex (lots of things can go wrong), and also a potential security risk. You should probably consider adding some code to ensure that the file's mime type ($imageFile->type), size ($imageFile->size) and other properties are legit, before calling $file->saveAs(). You might also need to create a UI for displaying and deleting the current image, and making sure old and no longer selected files are deleted from the server.

Finally, I'd posit that a vanilla browser file input is a pretty terrible user experience, compared to the Assets select input in Craft proper. There's all sorts of JavaScript libraries to help out with that, of course – in any case the above is hopefully a good starting point if you go down this road.


Display only one entry with checkbox checked in my pagination loop?

This should show all entries, paginated, with featured posts at the start, but not pinned to the top of each page.

{% paginate craft.entries({ section: 'blog', order: 'featurePost desc, postDate desc', limit: 5 }) as entriesOnPage %}

    {% for entry in entriesOnPage %}
        <article class="flex-container-small{% if entry.featurePost %} pinned{% endif %}">
    {% endfor %}

    {% include "partials/blog/_blog-pagination" %}

{% endpaginate %}

Ordering by featurePost is good, but you can perform the check a lot more simply.


Getting Wordpress 404 when accessing /craft/admin

Wordpress’ .htaccess file and Craft’s .htaccess file both use the same strategy: If the request is not pointing to a valid file or folder, rather than have Apache respond with a 404, re-route the request to index.php.

It sounds to me like you’ve got a .htaccess fie at your web root which is handling Wordpress’ index.php redirect, and that is taking precedence over Craft’s for whatever reason.

Since your Wordpress install lives within /blog/, you should move that Wordpress .htaccess file to /blog/.htaccess, so it’s only affecting blog/* requests. (You’ll also need to tweak it a bit; post the file’s contents if you need help with that.) Or another option is you could add this condition it, before the RewriteRule line:

RewriteCond %{REQUEST_URI} ^/blog [NC]

Likewise, Craft’s .htaccess file should live at /craft/.htaccess (no modification will be necessary as the one Craft ships with already accounts for the possibility that it’s within a subfolder), or a similar RewriteCond line could be added to it if you really want to keep all your redirects in one place at /.htaccess.


Discount Code applies to cart successfully but doesn't do anything. Am I missing something?

The reason for the discount not being applied is that nearly all your products have not been marked as promotable (by looking at your database):

Screenshot: http://jmp.sh/3FAK6NH

No sales or discounts can be applied to a non-promotable product.


Find an authorId based on first and/or last name

Well, I was 1 minute away from solving this, so I'll post my answer.

{% set author = craft.users.firstName(authorName.0).lastName(authorName.1).first() %}

Once the author object is set, you can access the {{ author.id }}.

Allowing me to neatly return author entries:

{% set entries = craft.entries.section('news').authorId(author.id).limit('10') %}


How to check for new entries periodically from the front-end?

This is actually a pretty simple task.

Create a template that your JS will reach out to returning the total number of entries. First create a template folder called "ajax" with an index.html file inside. Within that file put (replacing blogs with the name of your channel):

{{ craft.entries.section("blogs") | length }}

Inside your javascript, add this:

    var numberOfEntries = false;

    setInterval(function(){

    $.ajax({
      url: '/ajax',
      type: 'GET',
    })
    .success(function(data) {

      updatedNumberOfEntries = Number(data);

      if(updatedNumberOfEntries != numberOfEntries){

        // something was updated -- do whatever you want
        numberOfEntries = updatedNumberOfEntries;

      }
    });

    }, 5000);

You'll obviously need to make some revision to suit whatever you're trying to do but essentially just dump out the number of articles in a template, and use jquery's ajax method to get that value and see if it has changed.


Force an image transform to images inserted into Redactor

I wrote a plugin called Retcon which is able to apply bulk image transforms to images in HTML/Redactor content:

{{ entry.body|retconTransform({ width : 1024 }) }}
{{ entry.body|retconTransform(myAwesomeTransform) }}

There's currently no way to tell Retcon to only transform images that hasn't already been transformed, though – so this might not be exactly what you're looking for.


Will a change to verificationCodeDuration be updated retrospectively?

If you check UsersService->isVerificationCodeValidForUser(), you can see that it's taking the current date/time and subtracting the verificationCodeDuration config setting value, then comparing that to the verificationCodeIssuedDate time that is saved for that user in the craft_users table.  If the issued date/time is greater than the result of the subtraction date/time, then it's still valid, otherwise, not.

So because it's checking at runtime against the current date/time, the new verificationCodeDuration value will immediately take affect for any existing verification codes on a user.


Something like this in a .json file should work:
{
  "HTML.SafeIframe": true,
  "URI.SafeIframeRegexp": "%^(https?:)?//(www\\.youtube(?:-nocookie)?\\.com/embed/)%",
  "Attr.AllowedFrameTargets": ["_blank"],
  "HTML.AllowedComments": ["pagebreak"]
}

Note that the first two lines were adapted from https://stackoverflow.com/a/12784081/684 and the last two are the default options that Craft uses if no custom config is set.
Probably also worth giving this a read: http://htmlpurifier.org/docs/enduser-youtube.html


'Variable "assetSourceOptions" does not exist' after updating to Craft 2.6

It looks like the Redactor I plugin was incompatible with Craft 2.6... Fortunately, Brandon fixed this last night!

Update your version of Redactor I, and the problem should be fixed.


You mean how many rows the table has?

{{ matrixblock.superTableFieldHandle|length }}

Or the number of blocks of a matrix field?

{{ parent.matrixFieldHandle|length }}

To get the number of blocks for each row

{% for row in entry.superTableMatrix %}
    {{ row.matrix|length %}
{% endfor %}


Is there a query parameter to get categories that are related to anything else?

Add this to your chain...

.yourCategoryField(':notempty:')

It's not very well documented, but you can see it described in this old SE thread. In the docs, it's mentioned very briefly here.


Using a Dropdown field in a Matrix to parse a global

UPDATE: Knowing your use case I would use a dropdown as you were inside your matrix block and then query what the chosen value was and output the relevant global field.

{% if block.dropdownValue == 'globalName' %}
   {{ globalHandle.globalField }}
{% endif %}

You won't be able to do this dynamically but as you're adding the values to the dropdown matrix field you can add each 'case' to your template?

What you're trying to do isn't the usually use case for Globals. Globals are used more to output values in your templates independently from the current context (entry or section).

I would probably add the languages as categories and use a category field within your Matrix. This won't provide a dropdown but the UI for choosing a category has some extra features like the ability to search.

You will have the same control over the content as you do using Globals by adding fields to Categories.


I would go with Twigs batch filter, which exactly solves your problem.

Here an an adapted example:

{% set items = craft.entries({
    section: 'events',
    level: 2
}).find() %}

{% for row in items|batch(2, 'No item') %}
    <div class="row">
        {% for item in row %}
            {# Your entry #}
        {% endfor %}
    </div>
{% endfor %}


Can visitors 'force download' images stored on Amazon S3?

Headers passed back from S3 have to be set either on object upload or copy. You would have to use S3::copyObject() to copy the object to itself and set the appropriate headers (mentioned here: https://stackoverflow.com/a/25933113/2040791)

Alternatively, you can use the method mentioned in the same thread and force a download using HTML5, but that won't work on all browsers.


Use Imager plugin with AssetTransforms defined in admin panel

You'll have to define your transforms inline - Imager doesn't support named (i.e. CP-/admin-defined) transforms.


That means your server/browser isn't setting the proper application/json accept header for AJAX requests.


What is the best way to handle errors in plugins and templates?

Yep, Craft makes pretty liberal use of try/catch blocks. Wrap your HTTP request in that, and return whatever makes sense in the context – null, false, or maybe an empty array.

Probably also worth logging the error, so the developer can investigate why it’s not working, using Craft::log().

Remember when catching exceptions, that there’s a good chance the exception class won’t be in Craft’s namespace. So you’ll probably need to prepend the exception class(es) with \.

So to put it all together:

try
{
    // Make the HTTP request
    // ...
}
catch (\Exception $e)
{
    Craft::log('The request to domain.com failed: '.$e->getMessage(),
               LogLevel::Warning, false, 'mypluginhandle');

    return false;
}


Displaying Sub Categories on Category Page

It's hard to figure out exactly what your trying to do, but I can see a few potential problems.

No need for the 'num' variable, instead use loop.index (or loop.index0 for a zero indexed array); although I don't think you need it at all in this case.
nth() is currently returning the 'nth' offset of all assets that are related to all children collectively (thus the strange results). I would guess that you want the asset(s) related to the child category in the current loop. I would also guess that the asset(s) are defined in an assets field in the categories field layout, in which case you can get the asset(s) from the field directly, rather than using .relatedto(child).

Try the following — without understanding your structure entirely, it might at least be a bit closer to what you're looking for.

{% if category.hasDescendants() %}

    {% for childCategory in category.getDescendants() %}

                {% set asset = childCategory.myAssetsFieldHandle.first %}
                {% if asset %}

                {% endif %}

{{ childCategory.title }}

{{ childCategory.description }}

    {% endfor %}

{% endif %}

        {% set entries = craft.entries.relatedTo(category) %}
        {% for entry in entries %}

{{ entry.title }}

{{ entry.description }}

            Learn more
        {% endfor %}

Note: this is assuming that you want to show the subcategories and then the entries related to the main category. If not, then I misinterpreted your question and you will want to reconfigure this a bit, but the principles should be the same.


As Robin Schambach suggested I looked through my stack trace.
The request was fine but php couldn't find the template used on ajax-requests due to a misspelling error.

Fixed the misspelling – works like a charm.


Do I need 2 licenses for staging and production

One is enough you don't need a license for a development server at all source

And here is something from FAQ as well link

  Is there a way I can try Craft Client or Pro out before buying?
  Yes. As long as you’re running Craft CMS from a non-public-looking domain name (e.g. “mysite.dev” or “staging.mysite.com”), you will have the option to test the Client and Pro editions indefinitely.

And a info from the Terms and Conditions

  3. License Agreement Model
  This is a single-installation license, meaning you may integrate a Licensed Copy into one public-facing (“Internet”) or internal (“intranet”) web root directory at a time (the “Website”). You may also install and use Craft without limitation for local development and testing purposes.


Show matrix fields based on quantity [Sprig]

The problem that you expect your qty variable to be an array of guests and initialize it like that, but once you set a quantity it will be an integer, so the loop won't work correctly. See this line:
{% set qty = qty ?? [['']] %}

This initializes qty to an array containing another array containing an empty string (by the way, why do you need the nested array? Wouldn't a simple array of guest names suffice?). But once you select a quantity, the qty variable will simply be an integer (or numeric string, not sure). A for-loop expects an iterable (array or iterable object), so your for-loop is invalid:
{% set qty = 3 %}

{# this is invalid #}
{% for guest in qty %}
    {# this will never be reached #}
{% endfor %}

Instead of qty, what you want is a guests variable which holds a number of items in your expected format (in this case, arrays of strings) corresponding to the selected quantity. For example:
{% set qty = qty ?? 1 %}
{% set guests = range(0, qty - 1)|map(i => ['']) %}

{% for guest in guests %}
  <input sprig type="text" name="options[guests[{{ loop.index0 }}][0]]">
{% endfor %}

Note this will reset the values in the guest input fields whenever the quantity is changed. You'd need to retrieve the current inputs as well to set the current values of the input fields as well.


Manually override feed element in settings using the FeedMe plugin

This is actually a bit of an issue with XML-based feeds. To Feed Me, both your node's are link nodes. They have different attributes for sure, but Feed Me doesn't identify nodes by their tag and attributes, so it'll look at all tags called link to get the image.

As you've stated, you'll be getting a bunch of errors due to this. Can you restructure your feed at all? The ideal method would be to rename one to <image> for instance.

Right now, there's no way to manually define field mapping, as its already complicated. You're more than welcome to submit a feature request.


Forgive me if I'm wrong... by using loop.index0 is divisible by(2) are you trying to determine if the instance is odd or even?

1st - returns false
2nd - returns true
3rd - returns false
4th - returns true

If so Twig does support checking if the loop index is even or odd. Perhaps that would be better to use?

{% if loop.index is even %}Even{% endif %}

EDIT

I've just had a read of the Craft docs for the Case and Switch tags and found this:

  If you’re using the {% switch %} tag inside of a {% for %} loop, you won’t be able to access Twig’s loop variable directly inside of the {% switch %} tag. Instead, you can access it like so:

{% for matrixBlock in entry.matrixField %}
    {% set loopIndex = loop.index %}

    {% switch matrixBlock.type %}

        {% case "text" %}

            Loop #{{ loopIndex }}

    {% endswitch %}
{% endfor %}


Way for clients to edit translation file(s) in control panel?

I would say the most cleanest way is to handle all translations via Yii2 DbMessageSource.

You could say you want to store all translations into the database instead of files.
There is an MessageSource::EVENT_MISSING_TRANSLATION event in which you can store all translations into your new database table. As soon as Craft recognizes a new translation you'll have the chance to insert the new record

Here is a code snipped from our translation plugin

Event::on(
    MessageSource::class,
    MessageSource::EVENT_MISSING_TRANSLATION,
    function(MissingTranslationEvent $event) {
        if ($event->message) {
            $message = Translate::getInstance()->getTranslation()->addMissingTranslation($event->category, $event->message, $event->language);
            if ($message instanceof Message) {
                $event->translatedMessage = $message->translation;
            }
        }
    }
);

Your DbMessageSource class could look like this

class DbMessageSource extends \yii\i18n\DbMessageSource
{
    public $fallback = [];
    public $useMultiSiteTranslationFeature = false;
    protected $fallbackClass;

    /**
     * Return something for everything which is requested
     *
     * @param string $name
     *
     * @return mixed|null
     */
    public function __get($name)
    {
        try {
            return parent::__get($name);
        } catch (\Exception $e) {
            return null;
        }
    }

    /**
     * @param string $name
     * @param mixed  $value
     */
    public function __set($name, $value)
    {
        try {
            parent::__set($name, $value);
        } catch (\Exception $e) {
            $this->$name = $value;
        }
    }

    public function translateFallback($category, $message, $language)
    {
        if ($this->useMultiSiteTranslationFeature && Craft::$app->getRequest()->getIsSiteRequest()) {
            $this->useMultiSiteTranslationFeature = false;
            $translated = $this->translate($category, $message, $language);
            $this->useMultiSiteTranslationFeature = true;
            if ($translated) {
                return $translated;
            }
        }
        if (count($this->fallback) === 0) {
            return false;
        }
        if (!$this->fallbackClass) {
            $this->fallbackClass = \Yii::createObject($this->fallback);
        }

        return $this->fallbackClass->translate($category, $message, $language);
    }

    protected function loadMessages($category, $language)
    {
        if ($this->useMultiSiteTranslationFeature && Craft::$app->getRequest()->getIsSiteRequest()) {
            $category .= '_' . Craft::$app->getSites()->currentSite->handle;
        }

        if ($this->enableCaching) {
            $key = [
                __CLASS__,
                $category,
                $language,
            ];
            $messages = $this->cache->get($key);
            if ($messages === false) {
                $messages = $this->loadMessagesFromDb($category, $language);
                $this->cache->set($key, $messages, $this->cachingDuration);
            }

            return $messages;
        }

        return $this->loadMessagesFromDb($category, $language);
    }
}

The rest is common Craft work to create create a custom form/list for your new CP section or you create an element type and let Craft handle everything.

As you can see in the picture below: all translatable strings from all sources/categories/plugins are recognized and our customers are able to change all translations in all plugins into all languages. Even if the creator of the plugin never wanted to include certain translations into certain languages


Is it worth caching product blocks for use on a category page?

In short, it's worth caching anything that is at all time expensive, really.

It's always going to be significantly quicker to retrieve a cached chunk from the DB by key versus parsing a template section - and especially so a complex one with many related elements being pulled in.

However, if those are live products, i.e. with add to cart forms, you'll need to make sure the forms remain valid (think about current CSRF token, etc - you can insert these with JS on page load, for example) - and that your cache breaks whenever the cached thing is updated (which should mostly be automatic).

Note that once you start caching a lot of different things, it can take several seconds for all the stale cache chunks on complex pages to be deleted after you make changes in the control panel (you can see the little queue thing executing this after you save your updates) - so it will mean that your content changes will no longer be literally instant, and this can confuse if you're not aware of it happening.  In our case it can take up to a minute before it all washes through, so your content editors need to be aware of this.


Falling back to Parent Category if no asset exists

entry.brandFeature.one()

Is correct, you'll access the asset field and execute the one() function in order to fetch the asset.

entry.category.one()

Is correct too. You'll fetch the first category of your categories field

entry.category.one().categoryImage

Will access the categoryImage asset field of your category.

But then you do

categoryImage.getUrl()

So you try to get the url from the field value but you don't actually grab the asset that might be stored in the category.

categoryImage.one().getUrl()

However - keep in mind there could be entries without a category. Then you'll receive an error as well.


How do I make my variable available inside an assets loop?

Your problem is a scoping issue. You've defined theUrl inside the scope of a for loop, so it only ever lives inside of that loop.

You can do this to have it exist outside of the loop, too.

{% set theUrl = '' %}

{% for item in entry.customerLogoBarUrl.limit(1) %}
    {% set theUrl = item.url %}
{% endfor %}

{% for item in entry.customerLogoBar %}
    {% for asset in item.logo %}

    {% endfor %}
{% endfor %}


How can I make related entries and globals part of the search considerations?

I am going to guess that Search does work on rendered templates, so relatedTo items and globals would not figure into the results.

Is it possible to add something to the query string? If so, you could modify the search results page with a "related to" query.


Craft is using PHP and MySQL. What it gives you is a framework where a lot of the difficult stuff is already covered. Things like content modelling, user administration, security, etc is already done.

In addition there is a good plugin environment that can help fill in gaps to required functionality.

Of course, you can also extend it as you wish to add even more custom functionality.

For your particular use case I'd say Craft is a very good fit. You wouldn't need to be concerned with building an administration interface and the data you wish to store can be easily modelled.

Since your client wants to keep the spreadsheets then a plugin like FeedMe would be brilliant. You can set up an import in FeedMe and have it pull in the data from the spreadsheet using a cronjob or when your client wants to run an update. She'd just need to click a button. The data from the spreadsheet would be imported and used to create new, or update existing, content entries.

You might find that given Craft's really nice control panel she would also find that it's easier to enter data directly than follow the spreadsheet->import process.

So yes. Craft would be a very good fit.

Edited in light of your comment/question

You don't need to create your own database tables or write your own queries. That is what Craft is doing for you.

Craft is extremely flexible in that it will allow you to model your content pretty much however you wish. This data model is then stored within Craft's own database schema and content is written/read (by Craft) using the Yii/Yii2 PHP framework. You would then use the templating language (Twig) to create a front-end for the website with no need to use PHP at all.

So, let's say you had a Section of entries for Blacksmiths. Each Blacksmith is an entry, with whatever fields you wish stored within them.

Let's assume you want to list out all of the Blacksmith's stored in the Blacksmiths section to create an index.

You might do that within your template with Twig like so:

{% set blacksmiths = craft.entries.section('blacksmiths').orderBy('title').all() %}

This would give you an iterable object named 'blacksmiths' that you could loop over to output the content you want (taking a rough version of your actual listing page).

    {% for blacksmith in blacksmiths %}

        {{ blacksmith.surname }}
        {{ blacksmith.firstname }}
        {{ blacksmith.trade }}
        {{ blacksmith.year }}
        {{ blacksmith.notes }}

    {% endfor %}

If you wanted to alter precisely which blacksmith entries to retrieve you would include some additional criteria in your initial query. You don't need to worry about joins because the data has been stored within Craft's schema and Craft handles any criteria or relations that are required.


Asset routing issue in combination with slug and date

The mistake I made was entering "uploads/" in the url in file management. This should be "/uploads".


Ben gives some good practical updating advice.

And I agree with him that for the majority of cases, the best practice is to update locally, then push to production.

Just adding my 2 cents on top of that.

First, some background:

Being a self-hosted PHP web application is a hard life.  Your parents try to raise you correctly and equip you with the tools necessary to successfully go out into the world and live on some stranger's unknown, unfriendly and oftentimes hostile server environment so you can serve up web pages, but things are stacked against you.

For any given 1,000 web hosting providers, you will find 2,500 different environmental configurations... at least.  Different Linux distributions each with their own different libraries and versions.  Windows servers running IIS... or Apache.  Different permissions and user/group setups for each account.  Different versions of Apache and all of its modules... or nginx. Different MySQL versions each with different configurations.  Or "drop in" MySQL replacements that the host doesn't mention they're using, that's actually not a drop in replacement.  Or hosts that decide it's a good idea to store PHP sessions in memcached.

You'll find yourself living on fully-managed servers where you have limited to zero control of what you can do.  On boxes administered by weekend sysadmin warriors, running the bleeding edge of every piece of software on their box, because they read it on HackerNews.  You'll live on overloaded, underperforming, $5/month shared hosting accounts where the host has crammed 400 sites on one box and you get blamed for being slow.

Everything is broken.  It's amazing software works at all, much less the Internet.

How is a simple PHP script meant to survive is such as harsh world?!

Now that we've painted this picture of a horrible, bleak universe that Craft has to live in, let's look at some stats:

Auto-updating stats

Hard numbers:

Craft has successfully sent out over 8,100 auto-update requests.
94% of Craft installs with recent control panel usage are running Craft 2.
Since launch, we've received roughly 2,000 Craft-related support tickets.
About 370 of those tickets have been related to updating.

Soft, touchy-feely, by-the-gut numbers:

Of those 370 updating support tickets, I'd guess 90% of them fall into environmental issues that are mostly outside of Craft's control, but Craft tries to deal with as gracefully as possible.

Usually the culprits are either a) permissions aren't setup correctly and Craft can't download the update patch file, unzip it, or write to the craft/app folder to actually update the files b) during the update, Craft runs into a php.ini limitation... memory_limit and max_execution_time being the most common.

Both of these can be an issue if they are set low (32M and 30 seconds on older PHP installs or stingy hosts), or the size of your database has grown large enough that when Craft tries to automatically back it up during an update, it bumps into them.  That's a reason we added the backupDbonUpdate config setting.

We'll also see a spike in update errors related to these settings during bigger Craft updates (like 1.3 => 2.0) when we'll do an update to Yii, for example, that touches thousands of files.  More files in an update = more time to process the update = more of a chance of bumping into a limit.  Some people might prefer to do a manual update during those times, since that can finish executing quicker than an auto-update would.

Craft will also try to increase these limits for itself at runtime during potentially long running or memory intensive operations like updating, but that doesn't always work.  Some hosts have hard limits on them and things like FastCGI don't allow PHP scripts to use ini_set() in order to increase them at runtime.
5% of those tickets are related to bugs in a database migration that the update needs to run.  This usually occurs when we overlook some way that someone is using Craft and usually get fixed quickly.
The remaining 5% of the tickets were related to bugs in the updating logic in Craft itself.  We saw a few of these back in the 1.0, 1.1 and maybe 1.2 days, but honestly haven't ran into one in quite awhile (knocks on wood).

Does Craft practice safe-updating?

I think so.  We've got some ideas to try and further bullet-proof the process, but this is how it stands currently and is working out pretty well.

When Craft downloads an update patch file, it first validates the MD5 hash of the file to make sure that the file it received is the one it expected and nothing got corrupted during the transfer.  If a failure occurs here, we consider that a non-rollback failure - meaning, a failure has occurred, but no files have been updated, the database hasn't been touched and the site is still online - so no harm, no foul.
Craft will unzip that file to a temp location, grab the RequirementsChecker script from the recently unzipped file and run it, so that if any new requirements were added to be able to run Craft, and your server doesn't support them, you'll get a message stating so. If a failure occurs here, it's a non-rollback failure.
From the recently unzipped patch file, Craft will validate that all of the paths that it's about to update are still writable by PHP.  If a failure occurs here, it's a non-rollback failure.
Craft will now make a backup of all of the files/folders it's about to update by coping them from fileName.php to fileName.php.bak or folderName to folderName.bak.  If the update deleted a file/folder, it still gets a backup created.  If a failure occurs here, it's a non-rollback failure.
The recently updated files get coped over to their new homes.  If a file was deleted during the update, it gets deleted at this point.  If a failure occurs here, it's a file-only rollback failure and Craft will attempt to take all of the recently backed-up .bak files and put them back in their proper place and put the site back online.  The database hasn't been touched at this point.
If Craft is configured to backup the database during update, this is the point where a database backup gets created. If a failure occurs here, it will do a file-only rollback.
If the update came with any new database migrations (alter table schema, and/or data) to run, this is the point where they run.  If a migration fails, or any other error occurs, this is a full-rollback failure and Craft will attempt to restore the database from the backup it just made in step 6 to its last known working state, as well as perform the file rollback.
If we've made it this far, we're almost done.  All that is left is housekeeping.  Craft will try to delete all of the .bak files it created as well as flush various bits of info from cache.  If a failure occurs at this point, technically the upgrade is finished, so we don't attempt any rollback.


How can I stop a duplicate entry being created & provide feedback?

What about not showing the submit button at all, if a similar booking already exists?

{% if currentUser|length %}
    {% if entry.dateTime > now %} {# If event is in the future, display button to book #}

        {% set similarBooking = craft.entries({ sectionId: '18', relatedTo: ['and', { targetElement: currentUser, field: 'userBooking' }, { targetElement: entry.id, field: 'eventBooking' } ]}) %}
        {% set totalBookings = craft.entries({ sectionId: '18', relatedTo: { targetElement: entry.id, field: 'eventBooking' } }) %}

        {% if similarBooking|length %} {# Check if they have already booked #}

You have already booked a place for this event.

        {% else %} {# No previous booking, so check if there are spaces #}

            {% if entry.maxBookings > 0 %} {# Check if there is a limit on spaces #}

                {% if totalBookings|length < entry.maxBookings %} {# Check if there are spaces left #}
                    Book Now
                {% else %} {# There are no spaces left #}

This event is full.

                {% endif %}

            {% else %} {# No limit, display booking button #}
                Book Now
            {% endif %}

        {% endif %}

    {% endif %}

{% else %}
    Login to book
{% endif %}


Change position of entry types in a structure

This did the trick:

 craft()->sections->reorderEntryTypes($entryTypeIds);

Where $entryTypeIds is an array with all the id's in the correct order


How to conditionally hide particular plugin settings?

I'm not sure how to do a 3 way toggle with radio boxes, it might involve writing your own JS... but for the checkbox toggle it's pretty straight forward :)

{{ forms.checkboxField({
    ...
    toggle : 'toggleThis'
}) }}

<div id="toggleThis" {% if settings.eventClickDestination is not defined or not settings.eventClickDestination %} class="hidden"{% endif %}>
  //.. Form input goes in here
</div>

Craft will then take care of the toggling for you when the box is checked/unchecked


LJ Dynamic Fields - Only Seeing Latest 100 entries

By default Craft 2 will only return 100 elements (entries, assets, users, etc.) at a time.

If you want to get more than that, you need to use limit(null).

{% for channel in craft.entries.section('components').limit(null) %}

This behavior changed in Craft 3 so there is no default limit.


Since there is several moving parts here, i'll make a few assumptions.

You got a list of some kind with the product images and their containing metadata.
Your product image filenames have a consistent naming scheme. Something like product-condition1-01,product-condition2-01, product-condition2-02
You are able to write a couple PHP scripts and/or some frontend code that uploads your images, and then creates an list with the returned fileIds and the matching image filename. Take a look at AssetsService and the uploadFile action in AssetsController. For the uploading part, you can probably make a simple JS snippet that loops through the file list and uploads them.
After you got that list, write a script that runs through the product list (an CSV or something), and replace the placeholders matching your image filenames (product-condition-xx etc.) with the previous fetched fileId(s).
You will then end up with a comma-separated list of fileIds in your CSV fields, which Craft expects to able to relate the Assets to the imported Entries.
Import the entries with Import.
List the connected assets in your entries template the normal way.

I have not looked into how to save field info for Assets, but you can for sure make fields and then add them to the field layout for your Assets Sources.

(Not sure I understand all the conditions, but I think my outline should work pretty well for your case. Not able to comment yet, so I could not ask any questions beforehand. I'll update my answer if you add some follow-up information).


Make sure that the "Restrict uploads to a single folder?" setting in the fields settings isn't enabled. Enabling this, and not providing a valid path will give you that error I think.


Custom fields on a structure or section archive page

What you could do is make a "Global" Which sets the header image. You could name the global something like "Event Page Fields" or something like that so its clear for your administrator where to look.

The other option is creating a Single page and load all the structure items via the template there. This way you can add the image field to that single.


How to create any code from google spreadsheet like {.label} by Craft CMS

You need to use valid html/twig in your templates. Your “HTML Source Code” is not valid html. Removing the . from the beginning of your attributes i.e.: <span ex:content="genre"> should resolve the error, but it still wont be good html.

Best option, IMHO, is to start with a good solid foundation of valid html and work up from there.


getting redactor video.js plugin installed

Since the video button is supplied by a plugin, it should go under the plugins key rather than the buttons key. Your config would end up something like:
{
  "buttons": ["html", "format", "bold", "italic", "lists", "link", "file"],
  "plugins": ["video"]
}


How can I create a zip file containing all assets from an entry gallery?

I would recommend that you do this in php/plugin vs javascript. If you aren't familiar with writing plugins, you can start with the BusinessLogic Plugin — which is a great little plugin template, all set up with example controller, variables, and service file with example actions, methods, etc. Just drop in into your plugins folder, and activate, and you should be good to go.

There are a couple ways to set this up.

Use a form, plugin action, and pass urls or a gallery reference ID in a hidden form input field.

set up an HTML form (w/ your download/submit button)

add your custom action to your form (i.e. <input type="hidden" name="action" value="businessLogic/downloadZip">
add a hidden form input, and encode urls as a comma-separated list, or encode a gallery reference ID (i.e. <input type="hidden" name="galleryid" value="{{ entry.id }}">)

add a form action handler to your plugins controller file

lookup the urls (if not already provided)
generate the zip file and initiate download

Create a custom route, encoded with gallery ID reference

add a route to your config/routes.php file
set up your route action in your plugin's controller file with the gallery ID encoded as part of the route (i.e. 'downloads/gallery/13')
lookup urls using the gallery reference ID, generate zip, and initiate download

The advantage of using a custom route is that you can then just link to it from anywhere, or email the link to your client, without having to use a form. So, I would probably recommend using a route, unless you need to protect access for some reason.

To set up the plugin form action or route handler — have a look at the examples in the BusinessLogic plugin, which provides examples/instructions for both.

To grab the the URLs in your plugin method — you can use crafts built-in methods, as described in the craft docs.

To create the zip — doing a quick google search should come back with some good examples (like this one that has a sample HTML form and the php zip code).

Hopefully that will get you started — let me know if you get stuck, and I might be able to help further.


Is there a native function or plugin to allow admins to email all users?

Currently there isn't a native function to do this.

The only plugin that I know of that can do this, is Sprout Email from Barrel Strength Design.

EDIT:

I just released a plugin called Craft-Mailer which does what you are looking for.


Element API unable to get all() of matrix field

Figured it out in the end. As an array is being returned I just needed a for loop to get inside it.

Solution...

                    if($entry->relatedContent){
                        $index = -1;
                        foreach ($entry->relatedContent->all() as $block) {
                            switch ($block->type->handle) {
                                case 'relateContent':
                                    $index++;
                                    $relatedFeaturedEntries =  $block->featured->first();
                                    $relationsData[$index] = [
                                        'title' => $relatedFeaturedEntries->title,
                                        'url' => $relatedFeaturedEntries->url
                                    ];

                                    $relationsData[$index]['subItems'] = [];
                                    $relatedSubEntries =  $block->related->all();
                                    foreach ($relatedSubEntries as $relatedSubEntry) {
                                        $relationsData[$index]['subItems'][] = [
                                            'title' => $relatedSubEntry->title,
                                            'url' => $relatedSubEntry->url
                                        ];
                                    }
                                break;
                            }
                        }
                    }


The probably most easy way to do this is to sort the grouped array by key, which unfortunatelly is only possible with
a plugin, as Twig's sort filter only allows to sort by value.

Here I'm using Michael Rog's Supersort, but there are also other plugins that do this.

{% set allProfiles = craft.entries.section('members').order('profileLastname').limit(null) %}
{% set allProfilesGrouped = allProfiles|group("profileAlphabet")|supersort('ksort') %}


No more Ajax in the control panel after update to Craft 2.7.0

Prob solved; I auto updated to Craft 2.7.0 manually, and - stupid me for waiting that long to do that... - I updated it again manually. Problem solved. Case closed


Option for removing 'transfer content to' when deleting a user?

I can't think of a clean way without hacking core Craft files (which is generally not advisable).

Sounds like a reasonable feature request, though!


Can Control Panel Settings page become very slow with some plugins?

Is it a reasonable assumption that some plugins may affect Settings page loading time

It's very reasonable.  A plugin can do all sorts of things that might slow down CP rendering and it's reasonable to assume that all plugins don't test with databases that have 25 sections and thousands of entries.

The log files you want to look at are in craft/storage/runtime/logs. craft.log is the most recent and craft.log.1, .2, etc. being older. Do it with devMode enabled and you want to be looking at the timestamps for each entry to see where all of the time is being eaten up.

Alternatively (or in addition to), you can create a Github issue for CacheWarmer and let them know what you're seeing.

Sitemap is commercial, so you can go through the developer's usual support channels.


You could use either  | last filter instead of first or, a combination of first and another conditional ( segments[1] is empty or similar)?
{% set segments = craft.app.request.segments %}
{% if segments | first == “projects” and segments[1] is empty %}
Load scripts
{% endif %}

On phone so ymmv


How to get user's information when registering or logging in via ajax form

Not sure what other user info you're looking for, but Craft's UsersController will only return two things in the JSON response of a successful login for an AJAX request.

A success key set to true and a returnUrl key set to where the login redirect should go to.


Replace the /app folder, per the Manual Update instructions. It sounds like you may have already done this, but rolled it back.

Once the new /app folder is in place, you must visit the admin section. This will run any necessary migrations.

That's it!


Are you on Craft 3 or 2? In 3, you can use the built-in {% js %} ... {% endjs %} tag to inject scripts into tags named {{ endBody() }} or {{ beginBody() }} that you place wherever you like in your layout.

When outputting from the entry, also be sure to use the |raw filter.

https://docs.craftcms.com/v3/dev/tags/js.html

Craft 2 had a similar function: https://docs.craftcms.com/v2/templating/includejs.html

...Or you can just do it all manually with a Twig block - one thing that's a bit annoying about Craft's built-in tags is that they automatically include the
{% endblock %}

{% block extraFootData %}

    {{ entry.scripts ? entry.scripts|raw }}
{% endblock %}

Edit to add: I forgot to mention the one big advantage of using Craft's built-in methods over native Twig blocks is that they can work anywhere in the template regardless of the nesting level or scope of your blocks. For this reason it's usually preferable. (Even if you start with a simple inheritance model where each template @extends the layout, when the site grows and you start using shared intermediary templates to keep the code DRY, you can start running into very fiddly scope issues).


I'd set this up with regular date fields. You can then display the dates in whatever format you require on the front end using Twig's date formatting filter.

With the data stored as dates you can do a lot more with it compared to simply storing strings.

If you need to show a date range, such as "2013-2015" then it would probably be best to use 2 fields. A "date from" and a "date to" field. You could then use some logic to display one, or both, depending on whether there was something in the "date to" field.


relatedTo working for one category group but not another

Your approach seems interesting but you should never do such "relations". They can be broken all over the way. Let me explain that.

Title vs Handle

Most objects in Craft have the attributes title and handle. The title is the name that can be rendered in the frontend. This should be your attribute to show users what the object is about. The handle is your "developing" attribute. This is a unique field, with several validation rules to make this field selectable via getEntryByHandle() thus you can link entries via handle, get them via handle and change the display name (title) however you like and can still select those via handle.

Other Events in {{ thisCategory.title }}

Is totally correct, you show the title to the frontend

{% set category = craft.categories.slug(thisCategory.title) %}

Is absolutely wrong. The validation rules for title and the validation rules for the slug attribute are totally different and you should never match those fields. When you have a title like Foo Bar you'll never be able to match them since your slug would be foo-bar.

The correct way would be this

{% set category = entry.yourCategoryFieldHandle.first() %}
{% set entries = craft.entries.section('events').relatedTo(category).find() %}

If you really really want to relate objects not via the relation Field but via strings you should do it with the handle but never with titles or slugs


This is a misunderstanding of the difference between an ElementCriteria model and actual fetched elements.

Some useful background reading:

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

What are the differences between an elementCriteriaModel and fetched elements?

You could do what you're looking for using Twig's random method:

{% set projectImg = craft.entries.section('projekte').find() %}
{% set projectImages = [] %}

{% for item in projectImg %}
    {% set currentImage = item.bild %}
    {% set projectImages = projectImages | merge(currentImage) %}
{% endfor %}

{# Grab 3 random images from the array #}
{% for counter in 0..2 %}
    {% set asset = random(projectImages) %}

    <img src="{{ asset.url }}">
{% endfor %}


Forms are triggering CSRF Protection. Why would CSRF Protection trigger false positives?

We got this sorted before I finished my Stack Exchange question so I figured I'd share if anyone else runs into similar behavior.

After some troubleshooting, we learned that the issue here was that some of our Forms were being cached by Craft's {% cache %} tag and others were not.

CSRF Cookies are unique per user per session, so you don't want to cache them.

In our situation, it wasn't obvious at first that a {% cache %} tag was wrapped around the form, because the {% cache %} tag was actually in a {% block %} in a parent layout file that was being extended.

While searching through the templates helped us track down part of the issue, we also found it helpful to look at what was being cached in the craft_templatecaches table.  In the body column you can see what part of your template code is being cached, and we could see that the form, even though it didn't have {% cache %} tags around it in the template it was in, was being cached within a larger block of code.

Probably not the most mindblowing thing you will ever read, but it came in handy for me one long hour of one short day in history.


Merge element type errors? (title + hard-coded field)

You can pass the element off to ContentService::validateContent() in the event that it doesn't pass the record’s validation, just to get those  errors mixed into the element as well.

if (!$record->validate())
{
    // Copy the record's errors over to the element model
    $element->addErrors($record->getErrors());

    // Might as well validate the content as well,
    // so we get a complete list of validation errors
    if (!craft()->content->validateContent($element))
    {
        // Copy the content model's errors over to the element model
        $element->addErrors($element->getContent()->getErrors());
    }

    return false;
}


$view->hook('cp.entries.edit.details', functionThatReturnsView())

Is the correct way in Craft 3.


Filter and sort Commerce products based on Matrix blocks

I've tried the following, but it "obviously" gives me duplicate rows and my SQL and Craft/Yii knowledge isn't good enough to solve it. It's basically its own subquery with no relation to the "filters" in the query above, except for the title. I'm thinking that I could innerJoin on the initial subquery (which is the query/result from above) but don't know how ($base_products_query->subQuery equals NULL)?

$base_products_query->innerJoin('`craft_matrixblocks`', "`craft_matrixblocks`.`ownerId` = '".$category->id."' AND `craft_matrixcontent_product_sorting`.`elementId` = `craft_matrixblocks`.`id`");
$base_products_query->innerJoin('`craft_matrixcontent_product_sorting`', '`content`.`title` = `craft_matrixcontent_product_sorting`.`field_product_product_title`);
$base_products_query->orderBy('craft_matrixblocks.sortOrder');


Close!  This should do it:

{% set products = craft.commerce.products({
    relatedTo: (category),
    order: 'defaultPrice',
}) %}

With the quotes it's a string.  Without the quotes, Twig is expecting a variable you've defined called defaultPrice that doesn't exist.


Dev mode giving multiple errors but everything works

One of the things Dev Mode does is put Twig into a strict mode where it will throw an error any time a variable is referenced that isn’t defined. So that explains why you’re only getting these errors when Dev Mode is enabled. The errors should also show the part of your template code where the error occurred.

If you are certain that this is a bug, please send in a ticket from your Dashboard, including your DB backup and template files, so we can look into it.


Does Craft automatically sanitize user input?

First of all I would access the post using this format

Craft::$app->getRequest()->post('username')

Craft then extends the YII 2 request object. Does it sanitise input, not really, but models can set validation rules like this

https://forum.yiiframework.com/t/how-does-yii-handle-data-sanitization/83006


Add Entry Button Not Shown When Overriding Entry Sources

The New Entry button is not being displayed as Craft is not seeing my sources as containing publishable entries.

The Craft JS object contains a list of publishableSections which is checked by craft.js using this.getSourceByKey('section:'+section.id). Since my sources use a custom key value they are not included in this list.

So I have resolved the problem by adding my own New Entry button.


Extend templates from outside templates directory

You need to define and register your template roots for this folder:

Event::on(
    View::class,
    View::EVENT_REGISTER_SITE_TEMPLATE_ROOTS,
    function(RegisterTemplateRootsEvent $e) {{
        $e->roots['my-fancy-prefix'] = 'someDir';
    }
);


Decimals missing in result after adding up order totals for a customer

The trouble you are running into is trying to add a string value to an integer to get your total.

You have to use order.totalPrice without the currency filter to be able to add all the values together.

{% set cart = craft.commerce.cart %}
{% set totalOrders = 0 %}

{% for order in craft.commerce.orders.customer( craft.commerce.customer ).find() %}
  {% set totalOrders = totalOrders + order.totalPrice %}
{% endfor %}

{{ totalOrders|currency( cart.currency ) }}

Only apply the currency filter once all the calculations are complete.


Use Twig's batch filter with conditional

I don't think you can test a conditional against a batch set like this. I think it's testing each batched set against the conditional instead of each item inside the batched sets which is what you're going for.

I would just create a new set of filtered matrix blocks and then batch the result.

{% set onlyHalfWidthBlocks = [] %}

{% for block in entry.curatedContentBlocks if block.type == 'halfWidthBlock' %}
  {% set onlyHalfWidthBlocks = onlyHalfWidthBlocks|merge([block]) %}
{% endfor %}

{% for row in onlyHalfWidthBlocks|batch(2) %}

      {% for block in row %}
        {# ... block code here ... #}
      {% endfor %}

{% endfor %}


Route to Controller action (not in a plugin)

As it turns out it's not really possible to break out of the intended craft workflow. If you don't want to put additional business logic in plugins, you're only option is changing the index file. Which I did like this:

try
{
    $app->run();
}
catch(CHttpException $exception)
{
    // Implement custom route logic here
    // If nothing matches your own routes, just rethrow the $exception
    // like so:
    //throw $exception;
}

I'm more playing around here the learn how craft works, in the end the best solution is probably to just go with a plugin.


How do I add a local file to an asset field with a dynamically generated sub-folder?

I've now worked out how to do this.

As I have a copy of the entry that I want to save the file to, I can work out what the name of the dynamic folder will be called.

// Generate target folder name
$targetFolderName = $entry->slug; // or whatever you want

Next, I see if the folder has already been created:

// See if target folder exists
// I'm searching on the name of the folder, plus the id of the parent folder
// (see question above for how to find this)
$targetFolder = craft()->assets->findFolder(array(
    'name' => $targetFolderName,
    'parent' => $parentFolder->id
));

if (!$targetFolder) {
    // target folder doesn't exist so we must create it
    $targetFolder = craft()->assets->createFolder($parentFolder->id, $targetFolderName);

    if ($targetFolder->status == 'success') {
        $targetFolderId = $targetFolder->getDataItem('folderId');
    } else {
        throw new Exception(Craft::t("Failed to create new folder."));
    }

} else {
    $targetFolderId = $targetFolder->id;
}

// Now I can move the PDF from its temporary location into out new assets folder
$response = craft()->assets->insertFileByLocalPath(
    $localFilePath,
    $filename,
    $targetFolderId,
    AssetConflictResolution::KeepBoth
);

From here I followed the same code as in the question to add the asset to the asset field in $entry.


Free shipping discount on whole order doesn't appear as adjustment

For anyone else viewing this question - until there is a zero value adjuster as mentioned by Luke, my solution has been to simply do the discount checks in my custom module.
A little messy but it'll do the job for now.


How can I convert text into a URL-friendly string?

I was about to ask this question, but realized that it's closely related to this question.

The answer, like in the above referenced question lies with Twig filters.

Specifically, in this case, one needs to use the url_encode filter to convert the text needed.

Example

<a href="http://www.linkedin.com/shareArticle?mini=true&url={{ entry.url|url_encode }}&title={{ entry.title|url_encode }}&source=Xavier%20Creative%20House&summary={{ entry.question|url_encode|striptags }}" target="_blank">

In any case, I hope that helps others with this. I know how easy it is to forget that the answers sometimes like over in the Twig docs, and not Craft’s.


How do you set a different icon per entry in SmartMap?

That's a tricky one... Natively, all of the options are applied to all markers equally. But you can do a little workaround using something like this pseudo-code:

{% set markerIconJs  %}

    // On page load
    $(function () {

    {% for entry in locations %}

        {% if entry.lightswitch %}

            // JavaScript: Override the default icon with your own
            smartMap.marker['smartmap-mapcanvas-1.{{ entry.id }}.myAddressField'].setOptions({
                icon: '{{ entry.icon }}'
            });

        {% endif %}

    {% endfor %}

    });

{% endset %}

{% includeJs markerIconJs %}


Matrix entries field prevents following Matrix field to display

My suspicion is that the entry you are defining is confilicting with the entry that Craft gives you as the entry that this template is displaying. Try this, and see if it helps:

{% set blockLinkEntry = block.blockLink.first() %}
{% if blockLinkEntry %}

Find out more

{% endif %}


Yes, Craft would be a great solution for that!

For the proximity search feature, check out the Smart Map plugin. (Disclaimer: I'm the author.) It allows you to input addresses for each location, then your users can conduct a search to find the closest locations.


Switching to Craft from ExpressionEngine

You ask multiple questions at once – some of them quite broad. I'd recommend you create separate threads for each of your questions, and to try to be as specific as possible – e.g. elaborate a little on what you mean by "run multiple sites". That being said, in the event this thread isn't closed for being too broad I'll try to answer some of your main questions:

  Is it possible to run multiple sites using Craft?

Craft doesn't have an MSM-type feature, so short answer is no. See this thread for some further details and alternative solutions.

  Is there a plugin like Solspace Freeform for creating and managing
  forms?

Sure is. There's Sprout Forms which is a commercial, full-featured forms plugin, as well as a few free, smaller plugins such as Form Builder.

  How does site searching work. Would there be a way to tie this in to display local sites only?

I'd suggest you look at the official docs on searching in Craft, as well as the example search form.


First of all ->last() will always produce 2 queries, one fetches the total amount of results, the other one fetches the result with the offset given by the first query -> you can reduce the amount of queries by using first() if there is only one choice.

Furthermore: I would make use of eager loading so you don't even fetch the fields again and again (like currently)

{% set users = craft
    .users
    .group('members')
    .limit(null)
    .with([
        'firstChoiceLocation',
        'secondChoiceLocation',
        'thirdChoiceLocation'
    ])
    .find()
%}

Besides that - if you don't execute your $users query Craft might fetch the results again and again in certain circumstances so you don't have an array of elements but a query that is fired every single time

In the end I would highly suggest to not loop each user again and again, instead fetch the number of related users for each category via custom Query.
You can just count relations.targetId from the relations table where the sourceIds are your category ids and loop the result within PHP. I could show it for Craft 3 but I didn't use Craft 2 syntax for over a year


Problem with getHeadHtml(), getFootHtml() and caching

Regarding Problem 1

The Twig function {{ getHeadHtml() }} does only work with JS/CSS that are included before this tag. I had the same problem... you can find the answer/explanation of Brandon Kelly here: getHeadHtml() not outputting CSS included with {% includeCss %}

Regarding Problem 2

The {% cache %} does only cache the output HTML, no variables (see Is it possible to cache variables using the {% cache %} tag?). As a workaround you could cache the {{ getFootHtml() }} as well: in the first request it process the complete Twig code and stores the getFootHtml content correct. With this solution, you need to delete the cache manually (or with the onAfterSave event) after (re)saving, and adding/deleting an entry that could affect the cache.
Note: This does not work with {{ getHeadHtml() }} (see Problem 1).


Synching content and template files across environments

Here's a blog I wrote that might be useful to you: Database & Asset Syncing Between Environments in Craft CMS
This was written before Project Config was a thing, but the technique works great with Project Config too.


Make dimensions common for all variants in Craft Commerce

This is actually one of Commerce's best features IMO - that you CAN have separate dimensions/weights for variants - for us this is absolutely essential.
Of course, there are definitely times when it is not needed, too.
In these cases, we have a 'Standard Box' section that we store standardised entries in, with the appropriate data.
We then just relate these to the variant using a relations field.
Works really well...however, the behaviour is of course not the same as using the in-built fields - e.g. your shipping calculator needs to be aware of this etc.


Running Craft CMS 2 on MySQL 8.0+ (Any major considerations?)

Sounds like you've overcome the obvious ones already.
We've done some limited testing with the latest Craft 2 release on MySQL 8+ and no other red flags have been raised from our experience.


localhost and root directory for multiple site installs

Why not use MAMP Pro to define seperate local url's for your projects? Or use something like Virtual Host X.

This way you can define some made up url like: yourporoject.dev and point that url to the public folder of your project.


How to render entries on a singles page in a specific pattern/order?

How are the entries ordered (by date in a channel, manually in a structure or other?)

Are you using the entries anywhere elsewhere at all?

There are a couple of ways you could go, If the Galleries are related to the Updates, you could create a relationship from one to another using an entries field, and then just have the parent render the child in the same loop to different single page entry templates.

Depending on how the URLs need to be, you could use two different entry types in the same channel or structure.  If you need different URL structure you could always use {type} in the 'Entry URL Format' setting and then use custom routes if needed.

Hope this helps :)

I don't think you need to get as complex with arrays or anything.


How to create a static JSON files with Element API and cache it with Varnish

Not sure how you can do this, but you could manually print the response to a file yourself on a regular basis (as a cron job) using wget:

This:

wget -S http://craft.fira/fullmembers.json

…saves the JSON into a file named fullmembers.json into the directory it was run from.

Here is the solution that I have used in a cron job that runs every minute:

wget -O - http://www.fira.co.uk/fullmembers.json > /home/forge/www.fira.co.uk/public/jsoncache/fullmembers-temp.json
rm /home/forge/www.fira.co.uk/public/jsoncache/fullmembers.json
mv /home/forge/www.fira.co.uk/public/jsoncache/fullmembers-temp.json /home/forge/www.fira.co.uk/public/jsoncache/fullmembers.json


Database & Asset Syncing Between Environments

-bash: ./pull_db.sh: Permission denied

The error indicates that the shell script doesn't have execute permissions.  Running this command should make it executable:

chmod +x pull_db.sh


How do I sort and display event entries when each event can have multiple start times?

One thing you could do is have all screenings be Events, and then have Films be a type which contains the film's data, but use relationships to link to multiple Events which are the film's screening times. You could even have Events have two entry types: Events and Film Screenings (or something similar to this) so they could be displayed differently in the agenda view, and Film Screenings could link back to their parent Film entry.

Here's more information about using relationships and reverse relationships: https://straightupcraft.com/articles/introduction-to-relations-and-reverse-relations-in-craft-cms-with-examples

I'm not sure if this solution would fit your needs, but given my understanding of your issue, I think this is how I'd try to tackle it.


How can I pull every entry (large number) in a section?

You could use the {% paginate %} tag with ajax to limit the number of entries that are pulled at a time.


Setting unknown property when trying to join table

You can't set a property of an element in Craft that does not exists in the field layout, as a behavior or as a public/private attribute in the object. Craft/Yii2 will throw an exception because the property instance_datetime probably does not exist.

In order to attach a custom value you have to either create a new element or you have to store this information somewhere else.

Edit

You could the following as well to fetch your values and store them into a new array

$query = Entry::find();
$columns = $query
    ->addSelect('craft_event_instances.instance_datetime')
    ->innerJoin('craft_event_instances', 'craft_event_instances.entryId = elements.id')
    ->createCommand()
    ->queryAll();
$yourCustomValues = [];
foreach($columns as $key => $column){
    $yourCustomValues[$column['id']] = $column['instance_datetime'];
    unset($columns[$key]['instance_datetime']);
}
$elements = $query->populate($columns);


Multilingual MAMP port number siteUrl issue

Pretty sure the issue is that a port number won't work as part of the key in a multi-environment config.  Because unless you explicitly set CRAFT_ENVIRONMENT to use it, Craft is just going to use $_SERVER['SERVER_NAME'], which doesn't include the :port (that's at $_SERVER['SERVER_PORT']).

There's another thread here with some solutions/workarounds.


How do I hide tags in a category that have no entries?

Here's a good tutorial on how to achieve this: https://straightupcraft.com/articles/how-do-i-only-display-a-list-of-categories-that-have-entries-and-hide-empty-categories


Create a route to display entries with multiple tags

As long as you're using commas to separate the tag names in the URL:

mysite.com?queryurl&tags=cheese,egg,bacon&cat=sandwich

then you should be able to retrieve the multiple tags like so:

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

{% set tags = craft.tags.name(tagsString).find() %}

    {% for tag in tags %}

{{ tag.name }}

   {% endfor %}
{/ul>


Craft Commerce 2: PayPal Express not working - Correlation id: unknown

The Craft support helped me to figure this out. The problem was, that the CSRF wasn't properly disabled.

So in my config/general.php I have the following:

if ( !function_exists('isApiRequest') ) {
    function isApiRequest ()
    {
        $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
        $query = parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY);

        $actions = [
            'actions/charge/webhook/callback',
            'actions/commerce/payments/complete-payment',

        ];

        foreach ($actions as $action) {
            if ( strpos($path, $action) || strpos($query, $action) ) {
                return true;
            }
        }

        return false;
    }
}

return [

'*' => [

    'enableCsrfProtection' => !isApiRequest(),
    ...


Start with the manual: https://docs.craftcms.com/v3/extend/module-guide.html

This blog post covers module development in more detail:
https://nystudio107.com/blog/enhancing-a-craft-cms-3-website-with-a-custom-module

It includes a link to generate a scaffold module, which should work out-of-the-box.


How do I show something only for a parent segment and not it's children?

The lastSegment will always have length whether it's 2, 3, 4 etc. I am unclear about your Structure setup, but if there is nothing after "modules", "modules" is the last segment and therefore exists.

So maybe something like:

{% if craft.request.getSegment(2) == 'modules' and not craft.request.getSegment(3)|length %}


Get label from value in radio buttons list fieldtype

You could make a macro and use that as a "shortcut":

{% macro optionLabel(fieldHandle, optionValue) %}

    {%- set field = craft.fields.getFieldbyHandle(fieldHandle) %}
    {%- for option in field.settings.options %}
        {%- if option.value == optionValue %}
            {{- option.label }}
        {%- endif %}
    {%- endfor %}

{%- endmacro %}
{% import _self as macros %}

<h3>{{ macros.optionLabel('newsType', 'newsValue') }}</h3>


Display entries sharing the same nested category on an entry page

Get the first category of the entry you're currently on :

{% set currentEntryCategory = entry.categoryHandle.one().id %}

This assumes you limited the category to only be assigned once to the entry, otherwise you'll have to loop through all assigned categories to find the nested one you want.

Use that category ID to get the other entries that are relatedTo it :

{% set entries = craft.entries.relatedTo(currentEntryCategory).all() %}
{% for relatedEntry in entries %}
    {{ relatedEntry.title }}
{% endfor %}

If you want to exclude the current entry that you're on from the query :

{% set entries = craft.entries.relatedTo(currentEntryCategory).id('not ' ~ entry.id).all() %}


Sort entry titles alphabetically excluding 'The'?

According to SUBSTRING, the first character starts at 1.  So if you wanted to start at the position immediate after The (with one space), you'd need to start at position 5.

Just did a test locally and it works as expected for me if I use:

.order('(CASE WHEN title LIKE "The %" THEN SUBSTRING(title, 5) ELSE title END ) asc')


You need to call your setComponents function before you are trying to access your components otherwise - logically - they are not defined

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

    // define the components / services
    $this->setComponents(
        [
            'serviceExample' => ServiceExample::class
        ];
    );

    // access them
    $this->serviceExample->serviceMethod();
    // if it's easier for you to remember you can as well use the longer/slower syntax
    AbandonedCart::$plugin->serviceExample->serviceMethod();
);


Dynamically iterate over a matrix block's fields?

Not sure what you want to do with the fields, but you can access them through fieldLayout.

{% for block in entry.myMatrixField %}

    {% for field in block.getFieldLayout().getFields() %}

        {# get properties #}
        {{ field.getField().name }}
        {{ field.getField().handle }}
        {{ field.getField().id }}

        {# get value #}
        {% set handle = field.getField().handle %}
        {{ block[handle] }}

    {% endfor %}

{% endfor %}

You do kind of need to know what the field types are, in order to know how to display them. {{ block[handle] }} will fail for instance if one of the fields is an 'Entry' field, because you can't convert an ElementCriteriaModel to a string. To check the field type you can use field.getField().type;


How to use Twig to pull drop down menu items for a front end form

You'd do something very similar:

<select name="fields[fieldHandle]">

    {% for dropdownOption in currentUser.fieldHandle.options %}
        <option value="{{ dropdownOption.value }}"{% if option.selected %} selected{% endif %}>{{ dropdownOption.label }}</option>
    {% endfor %}

</select>


You can split your text

{% set text = block.heroTitle|nl2br %}
{% set splited = text|split('
')%}
{% for part in splited %}
    {{ part }}
{% endfor %}

If you need you can use the trim filter as well

{{ part|trim }}


How to add a user to a Users field from front-end form?

You would need to do this with a plugin that provides a custom controller, which looks at the post data and modifies the entries’ Users fields accordingly.

The controller action would look something like this:

<?php

$entryIds = craft()->request->getPost('entries');

if ($entryIds && is_array($entryIds))
{
    // Get the current user's ID
    $currentUserId = craft()->userSession->getUser()->id;

    // Fetch the entries
    $criteria = craft()->elements->getCriteria(ElementType::Entry);
    $criteria->id = $entryIds;
    $entries = $criteria->find();

    foreach ($entries as $entry)
    {
        // Update the Users field value with the current user's ID
        $userIds = $entry->myUsersField->ids();
        $userIds[] = $currentUserId;

        $entry->setContentFromPost(array(
            'myUsersField' => $userIds;
        ));

        craft()->entries->saveEntry($entry);
    }
}


Answer: As Brad guessed; the problem was a plugin, specifically Sprout Invisible Captcha. Disabling that allowed the form redirect to work properly again.


What is the easiest way to include bootstrap in Craft?

There are other ways, but since you've asked for the easiest, that's how I'd do it...
Just add it to /templates/_layout.twig and extend it to other templates: like /templates/index.twig starts with {% extends "_layout" %}
<!doctype html>

    ...
    <link rel="stylesheet" href="/css/bootstrap.css">
    ...

            {% block content %}{% endblock %}

// don't forget jquery/popper here

PS. Make sure `bootstrap.css` and `bootstrap.js` are placed in `/web/css` and `/web/js`


Need to build products page with filters (price, category,..etc)

I am using https://isotope.metafizzy.co/filtering.html for this. Really easy to use


Filtering search with checkboxes multiple param querystring

You can do this by getting all the params in the url that have the same name and joining them into a single string which you can use in your Twig template.

Note this code is untested but is based on something I've recently done. This example only uses categories but it's possible to expand it to search custom fields and/or add a free text search too.

{# get all the area params and join them into a comma delimited string %}
{% set areaQuery = craft.request.getParam('area') | join(',')  %}

{# build the search query #}
{% set relatedParams = ['and'] %}

{% set areas = craft.categories.group('areas').slug( areaQuery | split(',') ).find() %}
{% for area in areas %}
    {% set relatedParams = relatedParams|merge([{ targetElement: area }]) %}
{% endfor %}

{# execute the search and get a resultset of entries #}
{% set entries = craft.entries.relatedTo(relatedParams).order('score') %}

{# output your entries #}


Give this a try. I'm not 100% sure I've got my site set up the same, but I think it's close.

I have a category group called Categories. It looks like this:

Categories
    b2a
    b2b
    b2c

I created a section called homeBlocks which is a channel (shouldn't matter).
Then on my entry, I have a Categories field with a handle of categoryOne.

On my template:

{% set category = craft.categories.slug('b2c') %}
{% set entries = craft.entries.section('homeBlocks').relatedTo(category).find() %}

{% if entries | length %}
    {% for entry in entries %}

{{ entry.title }}

    {% endfor %}
    {% else %}
        {# No entries found. #}
{% endif %}

I have created 3 entries within my homeBlocks channel, and I've assigned the 1st entry and the 3rd entry to b2c.

Now I am seeing this when I view the page:

Entry Three

Entry One

EDIT

Sorry for the bad info - I think I understand what you are looking for now. I've updated my answer so give it another try.


The "verify user email" setting will keep anyone other than the user or an Admin from changing an email address


The code is correct, it was that I hadn't disabled the individual entries in the CMS, I'd only disabled the parent in the structure.

So adding .status('live') on the end of the for loop is the solution, and making sure every entry at all levels is disabled.


If you haven't solved it yet with a custom solution, have a look at my Auto Expire plugin. You would add a new expiration rule with the expiration date set to:

{ 'now'|date_modify('+3 month 5am')|date('c') }

or

{ postDate|date_modify('+3 month 5am')|date('c') }

and make sure the option to allow user changes is checked.


Site search that matches in more than one field

foo bar implies foo AND bar by default.  What you're probably looking for is foo OR bar.

If you look at craft_searchindex, you can see that keywords for fields are indexed on a per field basis, which is why you'd need the OR to search across multiple fields.

You can omit OR if you already know the field names ahead of time, though. field1:foo field2:bar.

You can see more search syntax options here.


Craft 2 to Craft update - timeout when updating database

The console command you are looking for is:
./craft migrate/all


How to set a different URL format for each entry type of a section?

You can set the URL format to something like this and it should work:

{% if object.type == "image" %}image/{customFieldHandle}{% elseif object.type == "articles" %}articles/{slug}{% endif %}


Error when trying to send HTML email on event onActivateUser

Changing sendNotificationEmail() to this should fix it for you:

public function sendNotificationMail(UserModel $user) {
    $mailer = craft()->email;
    $mailToBeSent = new EmailModel();

    $mailToBeSent->subject = Craft::t('Nieuwe gebruiker geregistreerd');
    $mailToBeSent->fromName = 'xyz';
    $mailToBeSent->sender = 'noreply@xyz.be';

    $mailToBeSent->toEmail = 'xyz@xyz.be';

    $originalTemplateMode = craft()->templates->getTemplateMode();
    craft()->template->setTemplateMode(TemplateMode::Site);

    $content = craft()->templates->render(
        '_emails/customer-service-notification',
        [
            'userInfo' => [
                'email' => $user->email,
                'name' => $user->fullName,
            ],
        ]
    );

    $mailToBeSent->htmlBody = $content;
    $mailer->sendEmail($mailToBeSent);

    craft()->templates->setTemplateMode($originalTemplateMode);
}


The BreakAndContinue plugin is an example of a plugin that adds a simple twig extension. I would start with that, and modify it to add the extensions extension (I assume that is this: https://github.com/twigphp/Twig-extensions ?) You might need to tweak the Twig PHP to get files to load etc., but not core Craft, since this will be a plugin.


Can SEOmatic pull from a Category Field to fill Entry - SEO Keywords or SEO Description?

Currently, no, SEOmatic cannot pull from a category field. You have two options:

Use the Preparse Field, and have that set to be whatever you want it to be (pull output from a Category, whatever): https://github.com/aelvan/Preparse-Field-Craft
Do it manually via Twig in your templates: https://github.com/nystudio107/seomatic/wiki/10.-Dynamic-Twig-SEO-Meta


/mysite/img/posts/ is an absolute path pointing to the root of your drive mount.

You probably just need to make it relative.  i.e. either mysite/img/posts or ./mysite/img/posts.


How to pull out all user data in a template?

If i understand your question correct, you like to output the user data. I don't think that you need the getContent() function. But it's important, that you use the first() function. Here is your code:

{% set userProfile = craft.users.id(userId).first() %}
{{ userProfile.yourFieldname }}

Hope it works.