How do I write an if statement to show Isotope filter button only if the Entry Section has content? I'm creating an isotope filter and have the following code. Could someone please help me write an if statement showing the buttons only if any of these entries have content. For instance the CD button if statement would check if the Entry "album" type "cd" and Entry "single" type "cd".

{# Albums #}
{% set albumCd = entries.section('album').type('cd') %}
{% set albumVinyl = entries.section('album').type('vinyl') %}
{% set albumCassette = entries.section('album').type('cassette') %}
{% set albumOther = entries.section('album').type('other') %}

{# Singles #}
{% set singleCd = entries.section('single').type('cd') %}
{% set singleVinyl = entries.section('single').type('vinyl') %}
{% set singleCassette = entries.section('single').type('cassette') %}
{% set singleOther = entries.section('single').type('other') %}

{# Collectable #}
{% set otherVideo = entries.section('other').type('video') %}
{% set otherMagazine = entries.section('other').type('magazine') %}
{% set otherPrint = entries.section('other').type('print') %}
{% set otherCollectable = entries.section('other').type('collectable') %}

<button class="filt btn" type="button" data-filter="*">show all</button>
<button class="filt btn" type="button" data-filter=".CD">CD</button>
<button class="filt btn" type="button" data-filter=".Vinyl">Vinyl</button>
<button class="filt btn" type="button" data-filter=".Cassette">Cassette</button>
<button class="filt btn" type="button" data-filter=".Other">Other</button>
<button class="filt btn" type="button" data-filter=".Magazine">Magazine</button>
<button class="filt btn" type="button" data-filter=".Print">Print</button>
<button class="filt btn" type="button" data-filter=".Collectable">Collectable</button>

Here's just a variation on the conditional that Victor provided that will do the same thing, might be a bit cleaner if you ever need to check several arrays:

{% if albumCd|merge(singleCd)|length  %}
    <button class="filt btn" type="button" data-filter=".CD">CD</button>
{% endif %}


Call Controller Method with Plugin Is it possible to call a method of a plugin's controller from within a plugin? I don't plan on making a habit of this but sometimes it may be needed. Just trying to plan ahead.

Thanks!

Something like this should work:

`craft()->runController('pluginHandle/controllerId/action');`

Although I'd question the decisions you've made to get to the point where you had to ask this question. ;)


Custom Labels for Address Fields Craft Commerce I need to be able to assign and output my own custom labels for the fields that are in the shipping/billing addresses during checkout in Craft Commerce.

I've already done so on the form like so:

{% set countries = craft.commerce.countriesList %}
{% set states = craft.commerce.statesArray %}
{% set addressFields = {
    firstName: {
        label: 'First Name',
        required: 1,
    },
    lastName: {
        label: 'Last Name',
        required: 1,
    },
    address1: {
        label: 'Address',
        required: 1,
    },
    address2: {
        label: 'Address 2',
        required: 1,
    },
    city: {
        label: 'City',
        required: 1,
    },
    zipCode: {
        label: 'Zip Code',
        required: 1,
    },
    phone: {
        label: 'Phone',
        required: 1,
    },
    alternativePhone: {
        label: 'Alternative Phone',
        required: 1,
    },
} %}

{% set modelName = modelName is defined ? modelName : 'address' %}
{% set model = address is defined ? address : null %}

    {% for key,options in addressFields %}

            {{ options.label|t }}{{ options.required ? '*' : '' }}
            <input type="text" id="{{ modelName }}-{{ key }}" class="u-full-width" name="{{ modelName }}[{{ key }}]"
                   value="{{ model ? model[key] : '' }}">
            {% if model and model.getErrors(key) %}
                {{ model.getErrors(key)|join }}
            {% endif %}

    {% endfor %}

That works like a charm. I need to however also be able to output it with my custom labels as well. Here is my currently template area, i'm not sure how i can get my custom labels in here. Please advise:

{% for address in addresses %}
     {% for key,value in address.attributes() %}

          {% switch key %}

               {% case "id" %} {# ingore #}
               {% case "customerId" %} {# ingore #}

               {% default %}

               {% if value %}

{{ key|title }}:

                                   {{ key == 'countryId' ? address.countryText : (key == 'stateId' ? address.stateText : value) }}

               {% endif %}

          {% endswitch %}

     {% endfor %}

I think you're looking for the attribute function:

{% set field = attribute(addressFields, key) %}
{{ field.label }}


Purchase Order in Craft Commerce I read through the docs for Commerce, but could not figure out how to use Purchase Orders with Commerce.  I am still working through the trial version to make sure Commerce can do what the client is wanting.  I know the paid version has a manual gateway.  Want to make sure it will allow the collection of a Purchase Order.

Jeremy I tried what you suggest.  Here is what I have...

    {% if not craft.commerce.paymentMethods|length %}

No payment methods available.

    {% endif %}

    {% if craft.commerce.paymentMethods|length %}
        <form method="POST" id="paymentMethod" class="form-inline">

            <input type="hidden" name="action" value="commerce/cart/updateCart">
            <input type="hidden" name="redirect" value="commerce/checkout/payment">

            {{ getCsrfInput() }}

            Payment Method

            <select id="paymentMethodId" name="paymentMethodId"
                    class="form-control">
                {% for id,name in craft.commerce.paymentMethods %}
                    <option value="{{ id }}"
                            {% if id == cart.paymentMethod.id %}selected{% endif %}>{{ name }}</option>
                {% endfor %}
            </select>

                Purchase Order Number
                <input type="text" name="purchaseOrder"
                    placeholder="Purchase Order"
                    class="purchase-order-field"
                    value="{{ formValues.lastName }}">

        </form>
    {% endif %}

I am not surprised that it is not working as I really don't know what I am doing here.  Sure my form is wrong.  Any suggestions.  With your help on other areas I am almost finished.  This is the last thing I need to do and I will be finished.  Any suggestions or help will be greatly appreciated.

There are many ways to skin this particular cat I'm sure, but the easiest way is just to use the manual payment gateway and a/some custom field(s) on your order to record the purchase order details.

Whenever you call the updateCart controller, from your input form where you gather the PO details, you can then pass in the POST parameters as fields[purchaseOrderDetails] to save the data to your field named purchaseOrderDetails for later processing.

Update using your code above:

{% if not craft.commerce.paymentMethods|length %}

No payment methods available.

{% endif %}

{% if craft.commerce.paymentMethods|length %}
    <form method="POST" id="paymentMethod" class="form-inline">

        <input type="hidden" name="action" value="commerce/cart/updateCart">
        <input type="hidden" name="redirect" value="commerce/checkout/payment">

        {{ getCsrfInput() }}

        Payment Method

        <select id="paymentMethodId" name="paymentMethodId"
                class="form-control">
            {% for id,name in craft.commerce.paymentMethods %}
                <option value="{{ id }}"
                        {% if id == cart.paymentMethod.id %}selected{% endif %}>{{ name }}</option>
            {% endfor %}
        </select>

            Purchase Order Number
            <input type="text" name="fields[purchaseOrder]"
                placeholder="Purchase Order"
                class="purchase-order-field"
                value="{{ cart.purchaseOrder }}">

    </form>
{% endif %}

All I have really done here is change how you're referencing the filed  on our order (which must have a handle of purchaseOrder for the above to work).  And I am presuming you have the cart available in cart obviously.

Don't forget to accept the answer if it gets you going!
Untested, but that's pretty much it, you were almost there really!


Sort matrix blocks by date and limit to 10 entries I'm loading multiple matrix blocks from multiple entries to the homepage if the date is today or in the future. So far this works but now I'm trying to sort the blocks by date and limit the output to 10 dates.

Here's the code I'm currently using:

{% for entry in craft.entries.section('projects') %}

  {% for block in entry.agendav2 %}

    {% if block.Datum >= now %}

      {% switch block.type %}

        {% case 'Datum' %}

              {{ block.Datum|date("d.m.Y") }}
                {{ block.locatie }}

              {{ entry.globalTitle }}
              {{ block.evenement }}

      {% endswitch %}

    {% endif %}

  {% endfor %}

{% endfor %}

Right now it's loading every upcoming date per entry like:

Entry 1: 31-01-2018
Entry 1: 01-02-2018
Entry 1: 02-03-2018
Entry 2: 30-01-2018
Entry 2: 06-02-2018
Entry 2: 03-03-2018
Entry 3: 23-01-2018
Entry 3: 25-01-2018
Entry 3: 08-03-2018

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

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

That's basically it.

Edit: you can search for entries in the future with

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

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

Edit:

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

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

And insert this in your PluginVariable

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

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

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

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

    return $allMatrixBlocks;
}


How Can I load Inline CSS in the Redactor Editor? In Redactor I put some content but I don’t know why Inline CSS is not load? Is there any way to solve this problem?

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

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


Can I have multiple comparisons within a single criteria parameter? The Craft site shows an example using a single comparison

Building upon this example from that page:

craft.entries.width('>= 100')

Can I do something similar but where 'width' is ALSO less than or equal to 200?

Conceptually:

craft.entries.width('>= 100 && <= 200')

You can combine multiple criteria like so:

{% set entries = craft.entries.width('and, >= 100, <= 200') %}

but what you can't do is to combine multiple statements to build more complex criteria:

{% set entries = craft.entries.width('and, >= 100, <= 200' or '>= 500') %}

in your case this wouldn't make much sense. But see my still unanswered question on this topic for another example: "Complex logic on a ElementCriteriaModel parameter?"


Add Redactor field to searchindex Is it possible to add a redactor field to the search index? I'm importing about 160 posts from a WordPress blog and the client has said it is absolutely essential that the posts themselves are searchable.
So far I've run /craft resave/entries  if I run with the flag --type 'blog' it only saves the titles, if I run --type 'postContent' (or --section) I get this error: No entries exist for that criteria.  (I'm not 100% on my knowledge of --type and --section).
None of the actual post content is in the search index and my entries are unsearchable.

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


How Do You Create A Navigation Of Entry Types? If I were to have entries of types: Book, Film, Note, Post and Bookmark. How would I automatically create a list of links (or a filter) to each entry type?

First, get your section. The following code will return you a SectionModel:

{% set section = craft.sections.getSectionByHandle('mySectionHandle') %}

Next, get the Entry Types off it. This will return you an array of EntryTypeModel objects:

{% set entryTypes = section.getEntryTypes() %}

From there you can loop through them to create your nav:

{% for entryType in entryTypes %}
    {{ entryType.name }}
{% endfor %}

You’ll want to create a Route which accepts those dynamic URLs (e.g. types/(slug)), and point it to a template like “types/_type.html”.

From that _type template, you can fetch entries of the requested type like this:

{% set type = craft.request.getSegment(2) %}
{% set entries = craft.entries.type(type) %}


Worldpay Offsite Gateway not redirecting to Customer Order screen on successful transaction I am having issues with Craft Commerce and Worldpay's Offsite Payment Gateway.  The way my clients accounts are set up with Worldpay, I cannot use the Worldpay JSON option so this I have to use the offsite method.

Basically, I have it working that its coming through as successful transaction on Worldpay's end - however I get left on the offsite thank you page, it doesn't redirect back to my local craft install.

Is there something that I need to do to trigger this? Because of this the order sits in my Orders under the Active cart tab, it does not fully complete.

Any suggestions appreciated.

Thanks

It turns out this installation is working as it should.  When I uploaded the website to a staging server and tested on it, it worked as expected.
 Redirecting me back to my Craft website, and showing the Customer Order screen whilst sending out relevant emails.

Not sure if it has been documented anywhere, but seems that this doesn't play ball when working locally.


MySQL keeps crashing Every couple of weeks or so, all the sites on my server (all running Craft) go down with the error message:

CDbCommand failed to execute the SQL statement: SQLSTATE[42000]: Syntax error or access violation: 1286 Unknown storage engine 'InnoDB'

It seems unique to Craft and unique to this server. None of the sites are particularly busy. It's likely a server thing, I know, but has anyone run into this and got a fix?

Thanks,
Clive

If you're sure that InnoDB is installed and enabled for MySQL on this server, that error can also happen when InnoDB fails to start - for whatever reason. i.e. insufficient disk space, log file size, corrupt data, etc.

Check your MySQL log files for the underlying error.


Dealing with long lists of items I'm looking for the best way to deal with long lists of items. In this case a subsite is a council library area which must publish a list of new books each month. In a perfect world I would suck this from the library catalogue directly, but that isn't going to happen just yet, so I need a medium term workaround. I also have other similar data lists to manage so need to have some solutions up my sleeve.

So I would have 50-100 list items manually added each month. Each item would consist of Book Title, Author, Some sort of ID number used in a link, and keys to the month (not necessarily published month) and type (e.g. non-fiction, fiction etc).

I can think of half a dozen ways to do this, but of course am seeking one that is efficient both from a data entry point of view, but also from a system and performance point of view. Ways of doing it might include (just from a brainstorming point of view):

Use a channel with each book being an entry (with fields for month and type)
Use a channel with each month being an entry and a matrix field for each book
Upload the monthly book list as an asset (XML or JSON) and display from there

The last one is the most appealing if I can work out how to get a non technical website content manager creating files in the right format (Excel should work for this). It also seems a short step from there to using a library catalogue system generated file.

I'm not quite up to writing my own plugin just yet, but perhaps it's time for me to learn.

I'd probably prefer to create the data using Craft's control panel UI for tags (→ book type) and dates than typing it all into Excel. So if it was me, I would probably vote for option a or b.

There shouldn't be that much of a speed differences between creating matrix rows or adding new entries for the data entry (there's this nice shortcut for "Save entry and create new one"), so my advice is to keep it simple and use a channel. Besides good performance (no relationship queries etc.), other advantages over matrix rows is to view and sort the books nicely in the CPs index view (customizable since Craft 2.3) or use the default disable switch (with traffic lights on the index view).

This gives your client a nice and flexible UI today and you can start developing a custom plugin that gets their system data into Craft. Even with that future solution it could make sense to have the entries available in Craft, to add website only data or make relations to other entries for example, and your plugin will be more of a custom import solution than a simple view to the external API data.


How can I populate a user field via a plugin? I have a plugin that listens for the users.onSaveUser. So when users register, an account is created, and I am creating an entry that will contain extended profile information. I am attempting to create a user field on that newly created entry to relate the entry back to the user account.

MyPlugin.php

$entry = new EntryModel();
$entry->sectionId = 16;
$entry->typeId = 1;
$entry->enabled = false;
$entry->authorId = $user->id;

$entry->getContent()->title = craft()->request->getPost('firstName') . ' ' . craft()->request->getPost('lastName');

// userAccount is the handle of the user field.
$entry->setContent(['fields' => ['userAccount' => $user->id]]);  // nope.
$entry->setContentFromPost(['userAccount' => $user->id]);        // nope.

...

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

Everything is coming across except the user field. I'm not sure what the field needs/is looking for to set it's value.

Relational fields are always stored as arrays, even if you are limiting them to only one entry so this should work:

$entry->setContentFromPost(['userAccount' => array($user->id)]);


Get related entries from matrix field I have a matrix field with one block type. In that block type, I have one field that is a related entries field.

How do I access the title from the related entries field from the matrix field?

Here is the setup I have:

Entry name is programs
In that entry I have a matrix block with handle name menuLinks
In that block, the related entries field name is called menuLink.

Thanks

Related entries in a matrix field are technically related to the matrix block and not the entry. So you will first want to get the related entries via relatedTo(block); then loop through the related entries to get the field values.

{% for block in entry.menuLinks %}
    {% set relatedEntries = craft.entries.section('SectionName').relatedTo(block) %}
    {% for entry in relatedEntries %}
        {{ entry.title }}
    {% endfor %}
{% endfor %}

If you know there is one and only one block or related entry then you can skip the for..in loop(s) and just use the .first() method (i.e. entry.menuLinks.first() and or  craft.entries.section('SectionName').relatedTo(block).first());

Keep in mind that if you are just trying to create a simple list of links to related entries you do not need a matrix field at all (unless of course you are doing something more complicated). The Entries Field Type itself can support an unlimited number of related entries (and are sortable), so you could just create an entries field directly in programs.


Email Template in Craft Commerce I have created a site for searching nearby restaurants and order items.

After ordering I wanna send a mail "Order received" with receipt attached in mail (if possible) to the customer + a mail to the respective restaurant which is in Craft->User "New Order" + a mail to site admin contains customer info and restaurants info + what I code in email template.

All these function will be done in single click. I mean when customer click on Order Now. These all mail will sent.

I am try to search email template and tutorial but I haven't found anything.

Let me know if anything in this help document needs clarifying: https://craftcommerce.com/support/sending-an-order-confirmation-email


What is the best way to track, record or view search terms? Pretty much like the title says - What is the best way to track, record or view search terms when using the built in Search form?

We track search terms on buildwithcraft.com the same way we track all other site activity: using Google Analytics.

All you have to do is throw GA event tracking code into your search results template.

If you’ve upgraded to Universal Analytics/analytics.js, use this:

{% set js %}
    ga('send', 'event', 'Search', 'Search', '{{ query|e("js") }}', {'nonInteraction': 1});
{% endset %}
{% includeJs js %}

If you’re still on the old ga.js, use this:

{% set js %}
    _gaq.push(['_trackEvent', 'Search', 'Search', '{{ query|e("js") }}', null, true]);
{% endset %}
{% includeJs js %}

There are other ways to include the JS, of course. (In our case we actually have a blank analytics block right alongside other Google Analytics instantiating code in the layout template, and set this JS code by overriding that block on templates that have custom things to track.) This {% includeJs %} route is just the most unassuming.

With that code in place, you’ll be able to start tracking “Search” events from Behavior > Events in your Google Analytics dashboard.


Pagination, display 'Next 20 Results' etc Just a quicky regarding pagination.
I have a paginated results list with a limit of 20 results in a page.

I'm wondering how I owuld go about making a pagination that shows the number of results on the next page.

i.e.
If I have 105 results, the pagination link says 'next 20 results', up to the fifth page, which would then say 'next 5 results'.

Not sure if there is an easier way to do it other than a load of maths to work it out.

Thanks!

Not sure about a load of math, but if you've got pageInfo setup like in the docs, should be something like this:

{% set totalPages = pageInfo.totalPages %}
{% set itemsPerPage = 20 %}
{% set currentPage = pageInfo.currentPage %}
{% set totalItems = pageInfo.total %}

{% set wholeItems = (totalPages - 1) * itemsPerPage %}
{% set remainderItems = totalItems - wholeItems %}

{% if currentPage == totalPages - 1 %}
    Next {{ remainderItems }} items.
{% else %}
    Next {{ itemsPerPage }} items.
{% endif %}


Restrict a users permission to only edit 'translatable' fields on a specific site? We would like to have a 'translators' user group, where the members can edit only the 'translatable' fields, but not the non translatable things (images, categories etc).

May be i missed something, but giving users permission to edit a specific site lets them edit all attributes.

Is there a way (permission/plugin/code snippet/best practice) to achieve that?

Thanks.

Thinking of writing a custom validation comparing old to new, or hiding/disabling fields via specific css.

Of course you can just remove the fields via CSS/JS but you could as well remove those fields from the visible layout from the beginning
Craft::$app->getView()->hook(
/**
 * @param array $context
 */
    'cp.entries.edit',
    function(array &$context) {
        /** @var Section $section */
        $section = $context['section'];

        /** @var \craft\models\EntryType $entryType */
        $entryType = $context['entryType'];

        /** @var Entry $entry */
        $entry = $context['entry'];
        /**
         * Array of field handles you want to remove
         */
        $fieldsYouWantToRemove = [
            'relation',
            'tag',
            'category'
        ];

        // include certain conditions you like, either by registering custom permissions and do
        // Craft::$app->getUser()->checkPermission('myFancyPermission');
        // or just search for the current users groups
        // Craft::$app->getUser()->getIdentity()->getGroups();
        if($entry->siteId === 4 && $section->handle === 'insertYourSectionHandle' && $entryType->handle === 'yourEntryTypeHandle'){
            // grab all the fields in the layout
            foreach ($entryType->getFieldLayout()->getTabs() as $tab){
                /** @var \craft\base\Field[] $fields */
                $fields = $tab->getFields();
                foreach ($fields as $key => $field){
                    // check if the fields handle is forbidden
                    if(in_array($field->handle, $fieldsYouWantToRemove, true) === true){
                        // remove the field
                        unset($fields[$key]);
                    }
                }
                // set the fields back
                $tab->setFields($fields);
            }
        }
    }
);

'cp.entries.edit' is a hook that enables you to manipulate all variables in the given context, so you check if the entry has a certain type and is in a certain section and remove all the fields from the tabs that you don't want to show.
You can register custom permissions for each field, for each site or you can even use events to check if the content has changed if you really want to make sure they didn't manipulate the HTML
edit
You can as well check for the translation setting in the field
if($field->translationMethod === Field::TRANSLATION_METHOD_SITE){
    unset($fields[$key]);
}

or
if($field->translationMethod !== Field::TRANSLATION_METHOD_NONE){
    unset($fields[$key]);
}

Whatever you need


On Craft Client, what does the client account get? A definitive description of the client account would be useful for this. What does a client account get? For example, can they clear the cache?

I know I can login and find this out myself, but it would be helpful to have a go-to article on this for future reference.

From here:

  The Client’s Account is not an Admin account like yours, so they will not be able to access the Settings section or administrate your Admin account. They’ll be able to do everything else, though.


Sprout SEO Re-saving Entries and metadata CPU 100% I added an element metadata field to my Sprout setup so that I could control things and automate a bit: Element Metadata Field

However, upon saving these field layouts, Sprout wants to re-save all entries. Fair enough, I quickly went through and added the layouts to all my sections. However, I've got 8686 entries, and so far this has taken 5+ hours on a 2 CPU server on Digital Ocean where the CPU is absolutely pegged. This server has 2GB of memory, and 3/4 is reserved for php/craft.

It seems every time I saved, it created new tasks for saving all entries, new regenerating search terms (it created thousands of regen search term tasks), etc. With multi-locale support for 10+ languages, this seems like it unleashed destruction.

Sprout SEO is running the Craft provided ResaveElements task when you save the field. The same ResaveElements task will run if you resave your Section as Craft needs to make sure that if you updated the URL of a section that it saves the right URLs to the database for all entries. (Sprout SEO is doing something similar making sure it has saved metadata needed for output). We have seen sites with a large number of locales experience load when resaving all elements and have seen similar with the resaving of Sections. In all cases where we've seen this, increasing server resources has solved the problem.

In the case this is just caused by a series of one-off changes where things were resaved several times in a row, you could delete the tasks from the craft_tasks table and retrigger the events so they are not triggered multiple times and see if that helps.

The best long-term solution will probably be to increase the resources on your server to ensure things go smoothly.


How to separate a parent and it's children when looping through a category? I have categories of cities and states set up as parents and children, for example:

California
  - Los Angeles
  - San Francisco

New York
  - New York City

When I use:

{% for place in entry.location %}
  {{ place }}
{% endfor %}

it returns to me the city state (for example: "Los Angeles California"). How can I separate out the parent and child? Ideally, I want to do something like this:

{{ place.child }}, {{ place.parent }}

Thanks.

If you have a 2-level category, and you select one of the nested categories (Los Angeles), what you get in your entry is Los Angeles and its parent (California). There is no way to have Los Angeles without also California, though you can have California without Los Angeles. Anyway, that for loop {% for place in entry.location %} will loop over both of them.

One way to be more explicit about the cities and the states is to loop over just the cities using level to fetch only the categories at a specific level in the category, and then for each city, fetch its ancestors with ancestorOf. Your code would look like this:

{% for city in entry.location.level(2) %}
  {{city.title}},
  {% for state in craft.categories.ancestorOf(city) %}
    {{ state.title }}
  {% endfor %}
{% endfor %}


How does Craft CMS cache with Redis? I don't understand how Craft CMS processes cache with Redis especially when saving to database/s?
My environment:

Craft Pro 3.4.8
PostgreSQL 12.2
PHP-FPM 7.4.3
Redis 5.0.7

I followed examples from the Application Configuration documentation and It seems that Craft CMS works well Redis. From inspecting both databases, sessions and queue work as expected.

queue table is created in SQL DB but empty because all queue related storage is moved to Redis where I can see all the keys queue.message_id, queue.messages and queue.waiting. queue table will probably always stay in SQL DB from installation process.
when a session begins token value is created in sessions table in SQL DB with some session related attributes and I also could locate the same token key-value in Redis DB with additional info about current session. When session ended token was removed from both databases.

Cache
I created some matrix field content and I cached it.
I found out that a row with cacheKey and other attributes (along with body column) are created in templatecaches table in SQL DB.
Since using Redis I expected that all/most of cache related storage will be stored in Redis. Inspecting Redis and I couldn't find anything to cache related stuff.

Craft only stores a small number of things in the Cache. As per this article (disclosure: written by myself) the things Craft will add to a Redis backed data cache are:

Available updates
Plugin store data
GraphQL query results
Some bits of data from the Craft Net API including license information
Project Config modification timestamps
Any data which is explicitly cached by plugins you have installed

Craft doesn't store any data which is cached using twig {% cache %} tags in the Redis backed data cache. The reason for this is discussed here but it boils down to the fact that Craft maintains a relationship between element queries inside the cache block and the cache results. This allows edits to specific elements to be traced back to all of the cache blocks that they might impact and should therefore be cleared.
Brandon puts it a little more succinctly:

[it] provides the most efficient cache-busting logic

Update 8th Sept 2020
Craft 3.5 now stores its {% cache %} tag data in the default data cache configured for Craft. If you are using Redis as Craft's data cache your template caches will now be placed there.
It also moves the cache busting logic out of the database and instead uses Yii's tag based cache invalidation. These changes should be significantly more performant and prevent previous issues with background tasks trying to clean up too many cache entries held in the database.


Craft 3: Non-Admin Users Can't Login Here's an odd one: I have a site with many users, only a few of them admins. Any admin user can login either via the /admin control panel or through a frontend login, which follows the example from the documentation.

Any non-admin users will be rebuffed on either login with an "Invalid username or password" message. Even more odd, if an admin user attempts to "Login as" a non-admin user from the control panel, it simply takes them back to the dashboard with a "Logged In" message, but keeps them logged in as their original admin role.

Any ideas on what maybe to look for or test?

I should've realized that this was a plugin issue, that changes everything. Thanks for the lead, Brad.


Preparse responsive images I'm trying to get Preparse Field for Craft to work on some responsive images set up with Imager for Craft, but I'm not having much luck, as it's still only generating the cached images on page load and not when the client saves the image.

This is my image code in the twig template. Can someone explain how to setup the preparse plugin with it as the explanation on the plugin page is a bit too brief?

{% set image = category.countyHero.first() %}
{% set transformedImages = craft.imager.transformImage(image,
    [
            { width: 1920, ratio: 3/1, jpegQuality: 75 },
            { width: 1366, ratio: 3/1 },
            { width: 1024, ratio: 3/1.5 },
            { width: 750, ratio: 4/3, jpegQuality: 60 },
    ],
    {
            format: 'jpg',
            allowUpscale: false,
            mode: 'crop',
            jpegQuality: 80,
            position: image.focusPctX ~ '% ' ~ image.focusPctY ~ '%',
            interlace: true
    }
) %}
{% if image | length %}
<img class="img-responsive"
     src="{{ transformedImages[1].url }}"
     sizes="100vw"
     srcset="{{ craft.imager.srcset(transformedImages) }}"
     alt="{{ image.title }}">
{% endif %}

I've managed to get it working via the following steps:

Create a new field and give it the preparse field type
Duplicate only the twig variable code from the template into the input box in the field page.
In Craft Settings, go to the page template, and add the new preparse field to the available fields (this doesn't show up in the content editor).
The twig template stayed the same.
The responsive images are then generated when the user saves the entry in Craft instead of when the page is loaded by the end user.


Can't Output Entries from Particular Blog Categories Trying to get all entries related to a particular blog category to output to the page. Right now I just get the correct URL for any category and a blank page.

Also my categories are entered into a matrix field as one of the matrix blocks. I use a single matrix field to capture all of the content for each blog entry.

Here is my categories/_category.html template code.

{# Fetch all of the entries related to this category #}
{% set category = craft.categories.slug('') %}
{% set entries = craft.entries.relatedTo(category) %}

{# Output them #}
{% for entry in entries %}
    {{ entry.title }}
{% endfor %}

I've tried plugging in particular category slugs into the craft.categories.slug('') but no help. I'm following advice from https://craftcms.com/support/entries-related-to-category

....and

Category Entries

Any ideas on what is missing?

First you'll need to know what you are currently doing

craft.categories.slug()

Will return a CategoryQuery with no property attached to it. So when you execute this query you'll fetch all categories. Your so called category variable is no category but a query that needs to be executed in order to do something

craft.entries.relatedTo(category)

Same thing again: it will return an EntryQuery with all entries that related to any category in any field. So as long as an entry has a relation to what every category it will match. Then again entries is not an array of entries but a query that needs to be executed via all()

When you loop through this query it is executed as well but with a deprecated warning because this way is not supported anymore.

If you are in a category page you'll likely have the catetory variable already injected as superglobal in your template. So there is already a category you have access to.

You can then do

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

Please make sure there are entries that are related to your current category


CP: Title from relation? I have the following 1:n relation between two sections:

Source Element: Interview
Target Element: Persons

In the CP (only there) I need to be able to identify Interviews by the name of the interviewed persons.

So in the title format field for the entry type I tried something like

{date}-{relation_interview_persons[0][firstname][lastname]}

But that's no good.

Is that even a valid approach?
Of course, we can simply use a custom title and that's it.

relation_interview_persons is not an array of elements but an object of type ElementQuery. In order to get the results you need to call one().

Keep in mind chances are high there is no related element if that's the case your code will throw an exception.

{% set person = object.relation_interview_persons.one() %} {{ person? person.firstname : ''}}

If date is not a field of type text but a Date field that will throw an exception as well since it's an object and no string


Craft redirect loop after logging in I'm experiencing weird cookie/redirect issues after logging in the admin/cp. Keeps redirecting to / (even on /) untill I've deleted my cookies.

Clean download/install, no errors occured. I have no idea what to check:

clean download of latest version 2.4.2700, no changes
different domain/hosting tested, still redirect occurs
different browsers tested, same results

Pulling my hair out here, any suggestions/ideas?

-- edit
It has to be a cookie/session related issue, but all paths are 'normal'. Using CentOS with cPanel, all up to date

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

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


Passing variable from block within including template I have this situation, where variable param doesn't exist.

skeleton.twig

{# Inject template #}
{% block var %}{% endblock %}
{% include '_includes/template' %}

Now I want to extends index.twig with skeleton.twig and output all rendered data.

{% extends "skeleton" %}

{% block var %}
    {# Set parameter #}
    {% set param = {
        section: ['handle1', 'handle2']
    } %}
{% endblock %}

template.twig

{% paginate craft.entries(param) as entriesOnPage %}
    {# data #}
{% endpaginate %}

As I go step by step in rendering process, I think, that the reason Why I'm getting this problem is because, the ECM is printed after {% include '_includes/components/feed/feed' %}.

Otherwise I have no idea, except I put wrong craft.entries(param)

Anything that is defined in index.twig outside of a block will be available in skeleton.twig, and so also in template.twig. This should work:

skeleton.twig

{% include '_includes/template' %}

index.twig

{% extends "skeleton" %}

{# Set parameter #}
{% set param = {
    section: ['handle1', 'handle2']
} %}


How can I tell if a variable is an array or an entry/element query? We have some components that are used to build pages, like normal, and some where we hydrate them with other data, so we are passing in arrays instead of entries.

If something is essentially an element, we need to do a .all() to not have deprecation warnings, but if you do that on an array, you get errors. I've read through A similar question with element queries vs arrays but since I'm not explicitly running a query on the page, this isn't quite applicable.

Both arrays and objects are iterable so that can't distinguish it. Ideally I'd like to do something like this:

{% if props.cards is array %}
    {% set cardArray = props.cards %}
{% else %}
    {% set cardArray = props.cards.all() %}
{% endif %}
{% for card in cardArray %}
...

Obviously, I'd be fine swapping the if/else conditions for the right test case

you can use the instance of twig test here.

You want to flip your logic, so test for Query object first else array stuff but this should work I think.

To get the specific class just {% dd props.cards %} in the template for ease.


Is it possible to stop Craft from logging so much? I've got a Craft CMS installation that is set to production mode. I notice that my logs get flooded with a bunch of entries which don't seem very useful.

For example, in a matter of several days, I've already got console.log up to console.log.5 - So it's rotated the log file 5 times already. These files are filled with what seems like every single query that gets executed on the website. They're 70k lines a piece. It also logs a lot of entries in queue.log, among other files.

How can I stop logging information and only log things which require my attention, such as errors?

Thanks!

As someone who theoretically might inherit your site one day... and also as future-you trying to diagnose a problem... please don't try to limit what Craft logs. If you want a quicker way to look for critical problems, check out the Yii2 Debug Toolbar as discussed here Profiling your Website with Craft CMS 3’s Debug Toolbar
You can use it to very quickly and easily see only errors, or only warnings, and so on. And then if the additional data that Craft logs is needed to help you diagnose a problem, it'll still be there.
To learn how to parse the Craft CMS log files quickly, check out the Zen and the Art of Craft CMS Log File Reading
If you do end up wanting to make your own logger, check out the Creating a Custom Logger for Craft CMS article
I echo Brad's comments, though, unless for some reason devMode is on, it shouldn't be logging every query, except for performance profiling.


Get the territory / country belonging to a locale? I'm asking, because I was trying to find out the whole afternoon. Found some posts, but they were related to getting all territories.

Example:

I have locales like English, French, Chinese and I'd like to add country to each related locale from territories, because each locale.php in /data folder has the values.

So it would looks like: Territory(United Kingdom) locale(English)

Code I'm working on:

{% set locale = craft.i18n.getCurrentLocale() %}
    {# Configure site locales #}
    {% set locales = ['en', 'en_gb', 'sk'] %}
    {# Check if locale equals the requested page locale #}
    {% if locale == craft.locale %}
        {% set current = true %}
    {% else %}
        {% set current = false %}
    {% endif %}

  {% for locale in locales %}

         ({{ craft.i18n.getLocaleById(locale).nativeName }})

  {% endfor %}

The output is a list of locales with native name:

(English)
(British English)
(Slovak)

If there would be a way to relate it's country to each locale from territories, that we wouldn't have to touch app folder to customize the lang files, like I read in other posts.
By doing so, We could achieve this:

World (English)
United Kingdom (British English)
Slovakia (Slovak)

Update

I think it moved on a little bit. With the code @carlcs provided, Craft was able to get a territory. There must to be some bug in it, because from 3 locales, It got assigned to only one territory (United Kingdom - British English).

Here is updated code.

 {% set locales = ['en', 'en_gb', 'sk'] %}
   {% for locale in locales %}
      {% set subTags = locale|split('_') %}
         {% set territory = subTags|length > 1 ? craft.i18n.getLocaleData(craft.locale).getTerritory(subTags|last) : '' %}

                 {% if territory %}{{ territory }}{% endif %} ({{craft.i18n.getLocaleById(locale).nativeName }})

  {% endfor %}

You can't get a territory name directly from a locale tag (e.g. 'en' or 'en_gb'). But what you could do is to
take the territory part of the tag (two letter country code; keep in mind, it's optional) and get the territory
name via getTerritory:

{% set locales = ['en_gb', 'fr_fr', 'zh_cn'] %}

{% for locale in locales %}

    {% set subTags = locale|split('_') %}

    {% set territory = subTags|length > 1 ? craft.i18n.getLocaleData(craft.locale).getTerritory(subTags|last) : '' %}

    {% set language = craft.i18n.getLocaleById(locale).name %}
    {% set language = language ?: craft.i18n.getLocaleById(subTags|first).name %}
    {% set language = language|replace("/- #{territory}$/", '') %}

    {% if territory and language %}

Territory: {{ territory }}, Language: {{ language }}

    {% endif %}

{% endfor %}


Using a macro for entries loop I'm trying to use a macro to output a list of entries (and the title of a section), this is my code:

{% macro sections(sectionName)%}

    {% set index = craft.entries.section('{{ sectionName }}Index').first %}

{{ index.getLink() }}

    {% for entry in craft.entries.section('{{ sectionName }}').order('title') %}

        {{ loop.first ? '
'}}

{{ entry.title }} {{ sectionName }}

        {{ loop.last ? '
'}}

    {% endfor %}
{% endmacro %}

{{ _self.sections('about') }}
{{ _self.sections('information') }}
{{ _self.sections('galleries') }}

But this displays ALL entries. However, if I hardcode the section names (for each loop) it works, though not DRY.

This is my first attempt at using a macro, seemed like a good place to use one?

You don't want braces within braces.

You want something like this instead:

{% set index = craft.entries.section(sectionName ~ 'Index').first %}

Same needs changing in the for loop.


Bizarre admin menu problem after upgrading craft to latest version Hi not sure if anyone has come across this issue before? I upgraded craft to the latest version on my test site. I have a few custom plugins that I have created on this site. The front-end seems to be working Ok. However I have a strange thing happening in the admin. The settings menu item is re-directing to one of my plugins?? So I can't access the settings at all. The menu link is showing as admin/settings and there are no routes set in either the routes.php config file or anything in the .htaccess.

Anyone any thoughts?

I've had this with the Dukt Analytics plugin, hitting Settings took me straight to the Analytics settings and nothing else.
Not particularly helpful in this instance but an upgrade to the plugin sorted the problem.


How to make combination of two field values unique? I make use of the front-end entry form for an event registration process. The event is the main entry, and every event registration an entry of a related registration section. The challenge is to see whether a user has already been registered for an event. Today, I do that with a database query before the entry form loads. But for some reason, this works not always (for example when users reload the page). How could I make the combination of two fields ("user id" and "registration status") unique? (Normally, I would do that on a database level with a unique index over the two fields.)

If I understood you correctly, you have two sections:

events
registrations

Is the user logged in? If yes, you can save the user id in your registration entry. In your events template you can check now, if a registration entry exists that is related to this event and the current user.
See example code (untested).

{% if currentUser %}

   {% set query = "userIdField:"~ currentUser.id %}
   {% set results = craft.entries({
      relatedTo: entry.id,
      section:'registrations'
      search: query
   }) %}

{% endif %}

{% if results|length %}
    user is already registered
{% else %}
    show registration form
{% endif%}

If your user is not logged in, you could (temporarily) store the registration information in a cookie (check out this plugin: https://github.com/lewisjenkins/craft-lj-cookies) and do a similar check.


Craft error on NFS filesystem I have a Craft 2 install that's been working fine until recently when the admin page is giving an error:

file_put_contents(): Exclusive locks are not supported for this stream

The front end is fine.

It seems (according to https://docs.craftcms.com/v3/config/config-settings.html) that NFS filesystems do not like Exclusive Locks, and the host uses NFS (the webserver the site is on connects to a backend filer via NFS to read the actual webfiles)

so I have tried changing

/config/general.php

so that useFileLock is set to 'false' but this hasn't changed anything.

Thanks in advance!

Two things:

Make sure you're using false the boolean and not 'false' the string.
After you change useFileLocks to false, clear the craft/storage/runtime/cache folder as I believe that setting is cached for whatever the cacheDuration config setting is set to.


Comparing matrix blocks by type and field value I’m trying to do something, the answer to which should be as simple as searching a Matrix field value but that’s not working for reasons I can’t fathom.
Setup

I have a Matrix field called programme.
It includes a block type called item.
That block type has a field with a handle of od.
I have a test case entry that has 4 item blocks in it.
All 4 of these blocks have a value in their od field but I need to check for scenarios where some or all of those blocks have that field empty.

So, I’m querying:
{% set talks   = entry.programme.type('item').all() %}
{% set odTalks = entry.programme.type('item').od(':notempty:').all() %}

…and then checking that works with:
<pre>
    talks: {{ talks|length }}
    odTalks: {{ odTalks|length }}
</pre>

…and the result I’m getting is:
talks: 4
odTalks: 0

I’ve tried other search values I know should work with the specific entry’s values, including regex strings. I've tried searching other fields in the block, and nothing works.
What could I be doing wrong?

Would be a shame to have to do something like this just to compare the lengths of talks and odTalks and act accordingly…
{% set odTalks = 0 %}

{% for talk in talks %}
    {% if talk.od is not empty %}
        {% set odTalks = odTalks + 1 %}
    {% endif %}
{% endfor %}

…even though that works and produces the expected:
talks: 4
odTalks: 4

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

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

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


Markdown filter, how to add HTML attributes? What's a good way to add attributes (classes etc.) to the HTML elements returned from the markdown filter?

This is what I currently do to add a class Bibliography to all generated <ul> tags from my articleBibliography field. Because there's never other content in this field, I'm save to replace them all.

{{ entry.articleBibliography|markdown|replace({'<ul>': '<ul class="Bibliography">'})|raw }}

--

Update:
You can also use the awesome Retcon plugin for this, it’s using DomDocument internally so the result should be more reliable.

{{ entry.articleBibliography|markdown|retconAttr('ul', {'class': 'Bibliography'}) }}


How to replicate "X days posted ago" I'm trying to build my blog functionality with craft, and struggling to get the functionality of showing "when" that post was created.

Is it possible to do the following:

Posted X days ago,
Posted x Weeks ago,
Posted x Months ago,

Straight Up Craft has a solid list of plugins.

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

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


How to get specific entries id I am attempting to get a specific entries id from within a specific section. I have looked around, and clearly have not found anything yet.

To clarify, lets say we have a section called "Stories", which is a structure. Inside of "Stories" there is a specific entry named, "Story One" that I would like to retrieve the id of.

I can pretty much get as far as getting the contents of the Stories structure via:

$entry = craft()->sections->getSectionByHandle('stories');

The important piece here, is that I want to find the "Story One" entry id. Reason being is that it looks like you can't do relatedTo queries via the title of an entry, but you need the id.

Correct me if iam wrong but cant you just use the ElementCriteriaModel. Essentially because you are looking for an element type using that will give you much more flexibility - bassicly it is a query builder on roids.

    $criteria = craft()->elements->getCriteria(ElementType::Entry);

    // Enter in params. here you can enter your sectionId
    $criteria->section = 'stories';
    $criteria->title   = 'Story One';
    $entries = $criteria->find();

This will return an array of all the entries that match this criteria. Ofcourse because this is craft you can thus enter a whole lot of other params and do some fancy stuff e.t.c..

I'll add two links at the bottom that are good reads on the subject:

https://craftcms.com/docs/plugins/working-with-elements

https://tighten.co/blog/craft-cms-building-complex-queries-by-extending-the-elementcriteriamodel


Download files in Assets fields I´m using for the first time Guest Entries plugin to collect some info and some files from users, great! All it´s going great, the site admin will see all the info that the clients sends and the files from each one, but i would like to know if there is a way to download the assets from a specific entry, so keep it simple to download the assets sended by some specific user.

Something like this plugin does, but it doesn´t work.
https://github.com/Hambrook/AssetLinks

I found this one too, but it downloads the assets of a entire source.
https://github.com/mattstauffer/craftcms-DownloadAssets

Any help? Thanks!

Change the javascript of the asset file to something like this and it will work

$(function(){
    $(".field .input .elementselect .element:not(.linked)").each(function(){
        var $this = $(this);
        if (!$this.data("url")) { return false; }
        var $a = $("<a class='icon'> </a>")
            .attr("href", $this.data("url"))
            .attr("title", "Download")
            .addClass("download")
            .addClass("sharebtn")
            .addClass("icon")
            .attr('download', $this.data('label'))
            .appendTo($this);
        $this
            .addClass("linked")
            .prepend($a);
    })
});


How do I display an entry's tag? I want to display an entry's tag next its title in a list of entries, and on the entry's detail page. For example, for a blog. How do I do that?

To list all tags on a particular entry use:

{% for tag in entry.tagField %}
    {{ tag }}
{% endfor %}

If you only want the first tag you can just use:

{{ entry.tagField.first }}


Validating a field value is unique I have a custom field type which I need to be unique. So far I have this:

/**
 * Validates the field values is unique
 *
 * @param mixed $value
 *
 * @return true|string|array
 */
public function validate($value)
{
    $existingEntryCount = craft()->elements->getCriteria(ElementType::Entry)->total(array(
        $this->model->getAttribute('handle') => $value
    ));

    return ($existingEntryCount) ? $this->model->getAttribute('name') . Craft::t(' must be unique') : true;
}

This works in that it returns an error if any entry is found with the value submitted, however I need to restrict the search so that it excludes the current entry from the search query.

If anybody is interested, I created a simple unique text field plugin that extends the core text field: https://github.com/fuel-digital/Craft-Unique-Text-FieldType.


Sorting across blocks (to get prev/next links) issue is an entry that has a matrix field named contents, whose blocks have an entries field named works, and the related works channel has an entries field named authorPeople.

Issue 1's contents consists of 2 blocks: A 'regular' section and an 'alumni' section. On the cover page, I loop through the blocks. For each block, I get the entries related to their authors, so that I'm outputting entries sorted by author last name, where some authors have more than one entry associated:

{% set contributors = craft.entries({
    section: 'contributors',
    relatedTo: { sourceElement: block.works, field: "authorPeople" }
}) %}

{% set articles = craft.entries({
    section: 'works',
    relatedTo: contributors
    order: 'lastName'
}) %}

That works fine, because I've got access to block.works. Any optimization tips are welcome :)

On the individual entry page, I want to getPrev and getNext entries spanning both blocks. So if you're at the last entry in the 'regular' section, your next link is the first entry in the 'alumni' section. And if you're on the first entry in the 'alumni' section, your prev link is the last entry in the 'regular' section. The last entry in the last section won't return a next link, so I can code in a link to another page, and the first entry in the first section won't return a previous link, so I can code in a link to the cover page.

Without having to loop through the blocks, how can I get that? Trying to order by issue.contents doesn't seem to work.

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

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

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

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

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

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

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

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

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


Remove subdirectories from admin URL with .htaccess I have Craft public files set up within subdirectories of a primary domain’s web root.

public_html/ # default web root
public_html/example.com/public_html/ # Craft public files here

The following .htaccess rules allow for the public_html subdirectory to act as the new web root. This is the .htaccess within the first public_html directory.

RewriteEngine on

RewriteCond %{HTTP_HOST} ^example.com$
RewriteCond %{REQUEST_URI} !^/example.com/public_html/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /example.com/public_html/$1

RewriteCond %{HTTP_HOST} ^example.com$
RewriteRule ^(/)?$ example.com/public_html/index.php?p=$1 [QSA,L]

It works until I go to example.com/admin.

I can login and cp works, but the URL is http://example.com/example.com/public_html/admin/dashboard

I'd like to remove the subdirectories from the above admin URL for mere aesthetic reasons, but can’t seem to nail it down.

Note: When going directly to http://example.com/admin/dashboard, for example, the URL remains as is, but all the internal links have the subdirectories.

I have Craft public files set up within subdirectories of a primary domain’s web root.
The following .htaccess rules allow for the public_html subdirectory to act as the new web root.

Is there a reason you're doing it this way? The .htaccess you have is only rewriting the content, it's not actually setting the web root. You're basically asking Apache to serve content out of the root for your other domain. There's only a couple circumstances I can think of where you'd need to actually do that (mirroring a domain for example but that's not something you probably want to do here).
For that, you need to set Apache's DocumentRoot properly for your second domain.
It sounds like you have a  CPanel based setup, where it's common for it to put add-on domains inside of the web root of the primary domain by default.  I'm not sure how the document root got changed to the primary domain but you need to set the document root of the add-on domain to the proper place (in Cpanel it's usually the Modify Domain function).
What you type in depends on your path but it's probably set to just public_html now. You want public_html/example.com/public_html/.
That'll get you back to a properly functioning setup.  Then just use Craft's default .htaccess file.


Multiple regexes/masks in Sprout Field validation Is there a way to include multiple validation masks in Sprout Fields? I've tried to do this (for my phone number validation):

#### ####|### ## ###

Since both of those are valid. If I try to write it out as a real regular expression, like this:

^([0-9]{4}) ([0-9]{4})|([0-9]{3}) ([0-9]{2}) ([0-9]{3})$

it just fails: preg_match(): Empty regular expression

Currently, Sprout Fields Phone Field only supports a single mask.

If you need more advanced pattern support, a Regex Field Type is probably the way to go.

Here is one that came up in my search:

mn_matchinput


Autocomplete of craft()->craft_pluginservice->foo() My IDE knows about craft() from an autocomplete and code validation point of view, but it knows nothing about the plugin services that have to be accessed in this way.

Any suggestions on how this could be improved to aid with easier development? Is it an IDE issue, or perhaps a Craft 3 feature request?

It's 95% an IDE issue.  Craft can take advantage of this because it provides PHP DocBlock property information in WebApp (which is what craft() is a reference to) and IDE's like PhpStorm are smart enough to analyze that and find the classes you're referencing for autocompletion.

It's impossible for Craft to let plugins dynamically add properties to that DocBlock, but I have seen some clever plugins provide their own abstraction around craft() so they can add their own plugin specific DocBlock info that enables autocompletion around services.


Create a route to display entries with multiple tags I understand how to set up a route and template that allows me to display entries by tag.

But how can I set up a template + route to grab multiple tags (if supplied but could just be one) from the url and display entires that have these tags?

I would also like to add a category element (showing all the entires from a category with the selected tags) but suspect much of that may be answered by the first part.

For example

Have a form the builds a url depending on user selections

mysite/queryurl&tags=cheese,egg,bacon&cat=sandwich

Is this possible?

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>


Output localized urls in navigation Does {{ url('handle') }} output the right url for localized sites?

I have a fr/en site and both lang output the english paths, but shows the right content and language/strings on the page.

I'm a bit confused. How do you guys build your navigation?

Yes, {{url('handle')}} will output the correct URL for whichever localization your user is currently in. Be sure to adjust your siteUrl configuration in your app/config/general.php file. Depending on your set up, it can look something like this:

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

For more information, check out Step 4 in the Localization Guide.


Sprout Forms: gather data from the page a form is on I want to gather data from the page a form is on and submit this information to the form entry.

Use case:

On an 'Events' entry page (the form is in the sidebar)
When the user fills in the basic form and submits, I want to get the entry's title and some custom fields in addition to what the user has filled out

In short what I want the form entry to submit is: Name, Email, Tel No, Message IN ADDITION to Event Entry Title, Date, Excerpt.

I think this is possible with hidden and invisible fields, but I may misunderstand their purpose.

-

After this form has been submitted I would like Sprout Email to get a hold of this data - so I need to know how to output this data when setting up the template in the back end text area for the email as well.

Could anyone offer any assistance on this please? I would greatly appreciate it. Thanks!

You're understanding the purpose of the Hidden and Invisible fields correctly and your desired workflow is possible.

Let's step through each part:

Hidden and Invisible Fields

These fields allow you to capture values on the page that the user doesn't see.  This includes any variable available to the page your form is being submit on. The key thing to note is that by default, all variables may not be available and for some variables, you will have to take an extra step to make them available.

By default, the only dynamic variables available to the Hidden and Invisible fields are variables that are global in scope like {{ craft.request.path }} or something like that.  To make an entry variable available, you will need to use the addFieldVariables tag on your page:

{# This line makes the entry variable available to your
   Hidden and Invisible Field settings. #}
{% do craft.sproutForms.addFieldVariables({ entry: entry }) %}

{# After you use addFieldVariables, you can display your Form as normal #}
{{ craft.sproutForms.displayForm('contact') }}

With the code above in place, you can now use any values that you want from the entry in your Hidden or Invisible Field Settings like {{ entry.title }}, {{ entry.postDate|date('Y-m-d) }}, {{ entry.excerpt }} or even loop through an array of data like Entries or Users, just like you would in your Twig template (as long as your final value can be stored in a PlainText field.

Dynamically access form data with Sprout Email

To send this information in a notification email, you'll first need to setup a new Notification in Sprout Email and select the rule "When a Sprout Forms entry is saved".

When your form is submitted, your Sprout Email template will have your entire SproutForms_Entry object and all of the submitted fields available to it via the object variable.

So, while your entry values were available to your form as:

{{ entry.title }}
{{ entry.postDate|date('Y-m-d) }}
{{ entry.excerpt }}

They will be available dynamically to your email template as:

{{ object.title }}
{{ object.postDate|date('Y-m-d) }}
{{ object.excerpt }}


Getting an entry's tags I'm trying to find a way to get tag data from a Model. Currently, I have a template that makes use of tags in an entry like this:

Codes: {% for tag in entry.codes %} {{ tag.title }}; {% endfor %}

When I create this template, I also need to send some of the data (specifically this data) to an API. Assuming I have an $entry object, how do I iterate through the tags that I need, or get an array with all the tags associated with an entry?

If you have $entry, you should be able to get the tags by the field name, (codes, in your case).

$tags = $entry->codes;
foreach($tags as $tag)
{
    echo "<li>".$tag->title."</li>";
}


lowercase breadcrumbs How do I parse the breadcrumbs code:

{% if entry.level > 1 %}

        {% for crumb in entry.getAncestors() %}

{{ crumb.getLink() }}

        {% endfor %}

{% endif %}

into lowercase?

Home > blog > entry title

or

  home > blog > entry title

You can do this with CSS, or with Twig.

CSS:

ul.crumbs li {
  text-transform: lowercase;
}

…or, if you need to start after a particular index…

ul.crumbs li:nth-child(n + 2) { /* Start with the 2nd `li` */
  text-transform: lowercase;
}

Twig:

{% if entry.level > 1 %}

    {% for crumb in entry.getAncestors() %}
      {# Build the link yourself, passing just the title through the `lower` filter: #}

{{ crumb.title | lower }}

    {% endfor %}

{% endif %}


Group specific entry from section Can this be done? I have a section called Bookings. I have 2 user groups A and B.

I would like both groups to have access to the section (bookings) but for some of the entries in the section, I would like to exclude one of the groups. Giving access to only A or B.

thanks.

Craft doesn't have an entry-level (or even entry type-level) permissions system; it's only possible to define permissions for sections.

Of course, "anything" is possible with a custom plugin, but without knowing more about your use case (what's the criteria for excluding group A or B for a particular entry?) it's difficult to advise further.

If you can edit your question and elaborate on the use case/goal, I might be able to update this answer.


How should I setup my .htaccess file I want to point any domain.com/page to the www.domain.com/page without showing index.php in my urls.

I have a www and non-www A record pointing to an IP address.

How do I set up my .htaccess file to do this?

Here's what I'm using:

# Remove the www from the URL
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

# Exclude root files
RewriteCond $1 !^(favicon\.ico|favicon\.png|fb_share\.jpg|apple-touch-icon\.png|apple-touch-icon-precomposed\.png|index\.php|robots\.txt) [NC]

# Exclude asset folders
RewriteCond $1 !^(assets|uploads)/ [NC]

# Remove index.php
RewriteRule ^(.*)$ /index.php/$1 [L]

You could also set up a CNAME record from www.domain.com to domain.com in your DNS.


descendantOf() parameter, entryModel or ID? I'm confused about what to pass as a parameter in the descendantOf() function.
I'm developing a website and passing an entry ID as a string (I also tested it as an integer) and everything went fine, untill now. Suddenly, when I try to use it with new template code, that doesn't work anymore. It does however still work in my template I wrote last week.

The docs say that the parameter has to be an EntryModel:

  descendantOf #

  Only fetch categories that are a descendant of a given category.
  Accepts a CategoryModel object.

In this thread on SE, someone says it can be an Entry ID.

  descendantOf accepts either an EntryModel object or an entry’s ID.

However, if I use the next code (category is not a category group, I'm using a structure for it) where currentRegionId is an entryId as a string or integer:

{% for productCategory in product.productCategory.descendantOf(currentRegionId).order("title asc").find() %}

This works. But according to the docs, it shouldn't work, because I'm passing an ID and not an EntryModel.

It also works when I pass that ID while using eager loading:

{% set mainCategories = craft.entries({
    section:            'productCategories',
    level:              2,
    descendantOf:       currentRegionId,
    limit:              null,
    with:               ['productCategoryIcon']
}) %}

However, if I try the next piece of code in another template:

{% for category in entry.applyToCategories if category.descendantOf(currentRegionId) %}

I get this error:

  Argument 1 passed to Craft\BaseElementModel::isDescendantOf() must be
  an instance of Craft\BaseElementModel, integer given

If I pass an EntryModel it does work as expected and according with the docs:

{% for category in entry.applyToCategories if category.descendantOf(craft.entries.id(currentRegionId).first()) %}

So what's going on? Is it something with the way I fetch my entries?

These are two different things.

{% set entries = myEntryModel.myEntriesField.descendantOf(var) %}

In this case the Entries field returns an ElementCriteriaModel object and you are setting the descendantOf parameter, which does in fact accept EntryModel objects or an Entry ID as an integer value. The Craft documentation is incomplete in this regard.

{% set bool = myEntryModel.isDescendantOf(var) %}

Here you are using the method isDescendantOf that is available for an EntryModel and returns whether the entry is a descendant of another entry. This method apparently only accepts an EntryModel.


Charge Plugin - Stripe payments occasionally not being received in craft I have some Charge payments on my website, and I have registered the onCharge event in my plugin, like so:

public function init()
{
    parent::init();
    craft()->on('charge.onCharge', function(Event $event) {
        // Function logic here
    }
}

And 95% of the time it works, but sometimes it doesn't trigger. The transaction goes through, and I can see in my Stripe account that it has been successful, but the payment does not appear in my Charge Logs in Craft, and the onCharge event never triggers.

Can anyone help? Any suggestions?

Thanks, Jai

At first glance I cannot tell you why your plugin runs intermittently.
But if your plugin is interacting with Charge, there are some log functions you can use that may be helpful.

craft()->charge_log->email("yada yada");
craft()->charge_log->note("yada yada");
craft()->charge_log->error("yada yada");


Building Results From Advanced Search Form I'm building an advanced search form and having some difficulty with getting the results. The form inputs include price and year ranges. For example, search for used cars from $10,000 to $20,000.

The search is working, here's my results page code:

{% set manufacturer = craft.request.getParam('manufacturer') %}
{% set model = craft.request.getParam('model') %}
{% set bodyStyle = craft.request.getParam('bodyStyle') %}

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

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

{% set results = craft.entries.section('usedCars').type('entry').search().manufacturer(manufacturer).model(model).bodyStyle(bodyStyle) %}

This is how i'm showing the price range.

{% if minPrice|length and maxPrice|length %}
{% for entry in results if entry.price <= maxPrice and entry.price >= minPrice %}

{% if minPrice is empty and maxPrice|length %}
{% for entry in results if entry.price <= maxPrice %}

and so on etc...

The trouble with this method is it's all based on a whole stack of "IF" statements and when I start to think about adding the year ranges too, my head starts to hurt. Is there an easier way to achieve the same thing?

I'd appreciate any nod in a general direction, or help simplifying my code down...

You can set multiple conditions on a single ElementCriteriaModel parameter. Pass it either a comma-separated list as a string or an array of conditions.

{% set entries = craft.entries.id('84, 62, < 7, 29') %}
{% set entries = craft.entries.id([84, 62, < 7, 29]) %}

In this example, each entry with any of these IDs is returned (→ or logic).
To return only those entries that match all criteria of your list (→ and logic), set the first value to and:

{% set entries = craft.entries.id('and, > 100, < 200, not 110') %}

In your case I'd set the "year" and "price" parameters as an array and combine it with all other craft.entries parameters using the object syntax like so:

{% set entries = craft.entries({

    section: 'usedCars',
    type: 'entry',
    manufacturer: manufacturer,
    model: model,
    bodyStyle: bodyStyle,
    price: [
        'and',
        '>= ' ~ minPrice,
        '<= ' ~ maxPrice,
    ],
    year: [
        'and',
        '>= ' ~ startYear,
        '<= ' ~ endYear,
    ],

}) %}

Make sure that your "year" and "price" variables are not empty by setting default values:

{% set startYear = craft.request.getParam('startYear') %}
{% set startYear = startYear is not empty ? startYear : '1900' %}


How might big Matrix/Relationship fields affect front-end CP performance? I frequently run into front-end performance issues in EE CP pages, where I have a big Matrix field (100+ rows), or a Playa field with a long list of entries (3000+ relatable entries), or worst of all, a combo of the two: The page gets really slow, and sometimes freezes, while JS initializes and renders all of those fields and their content.

I'm curious if the same issues would plague big Matrix/Relationship fields in Craft's CP. If not, what architectural differences make it so?

Matrix fields are going to suffer from similar scalability issues if you have a large number of blocks in a single field, affecting memory consumption, MySQL/Javascript performance, and usability. We consider that a bug (and it has been logged in our bug tracker as such), and plan on addressing it at some point in the future.

Relational fields have similar issues if you plan on selecting hundreds of elements. If you simply have a section with hundreds of entries, but don’t intend on actually selecting more than a handful, you don’t have anything to worry about; the element selector modal that comes up when you want to select additional elements is perfectly scalable, because it only loads 50 elements at a time, and lazy-loads additional elements as needed via an infinite scrolling implementation.


relatedTo() only on one field? I have a Product entry type that contains a field for Components (which are also products) and a field for Related Products (again, also Products). I want to be able to find a parent product from a Component, but using a relatedTo() gives me all the Products on which it is a Related Product as well.

Is there a way to specify which field you want to use with the relatedTo() method?

$product = Entry::find()->section('products')->relatedTo($component)->one();

Expected result = The parent product.

Actual result = A random product on which the component is a related item.

Of course, this was all working great until I just recently added the Related Products field.

Haha. I figured it out. Leaving the answer here in case anyone else runs into the same problem:

$product = Entry::find()->section('products')->relatedTo([
    'element' => $component,
    'field' => 'productComponents'
])->one();

You can pass an object/array to the relatedTo() method as described here:

Relations | Craft 3 Documentation


Bulk regenerate slugs I’ve already got a ton of content put in by the client, and there’s quite a bit of accented characters (é, à, ...) in the titles, and thus also in the slugs where they get url encoded, which my client considers 'ugly'.

Now I’ve added the limitAutoSlugsToAscii' => true rule to the config, but how can I best rework the url’s for the already existing content? There’s about 1000 entries already in the website so I’d rather not go over them by hand.

Can I just clear the slug column in the database? Or will I have to write a temporary custom controller action that I can trigger to loop over all entries to redo their slug? Or is there another (better) solution?

Or will I have to write a temporary custom controller action that I can trigger to loop over all entries to redo their slug?

This one.

The plugin could then just use StringHelper::asciiString($slug); to do the ASCII conversion and re-save it back to the database.


Fields applied to the User area are not translatable? I have a site which allows people to register as a member from the front end. I've got a bunch of fields attached to the User so that each person can build their own extended profile page; the site is bilingual. I've successfully got fields translatable when they're attached to a Section (the fields are marked as translatable), but when the same fields are attached to User there appears to be no way to input content in a different language; the familiar language switch in the back-end is not there... what am I missing?

E.g., here is the biography field, marked as translatable:

Here is the result when the field is used in a Section (note the interface has a language switch on the right, which can be toggled and the contents of the biography field changes):

But here is the same field when used in a User, note the lack of a way to change the language:

Bonus Question:
Assuming these fields are translatable; how would I get the front-end user form to list the fields in both English and Welsh so the user could fill in both on one page (i.e., without them needing to switch the site itself into another language)?

You're not missing anything; user content is currently not translatable. (It's up to each type of element whether it wants to support translatable content, and we felt that 99% of the time it would not be desirable for users to have translatable profiles.


Reverse relationship in Craft Commerce? I'm working with Craft Commerce with a set of individual items in a product type and in another, I have packaged sets of the same. The sets (cardSets) have a relation field to select the required individual cards. The code is in the product entry template for the individual card and my intention is to highlight that the single card can be purchased in a set.

I'm using the following code to do a simple reverse relationship but I can't get this to work and I'm not sure if I've got the syntax correct. I'm not seeing any return or error. How do I know if I'm getting an object back?

{% set relatedProduct = craft.commerce.products({
    type: 'cardSets',
    relatedTo: {
        targetElement: product,
        field: 'productsInSet'
        }
}) %}

{{ relatedProduct.title }}

When you use the craft.commerce.products tag, it will return a criteria model, but you are treating it as the first result by accessing the title attribute.

Try {{ relatedProduct.first().title }} instead.


Is the "registerSiteRoutes" hook screwing up my template path? This may be a bug...
I have a controller action which has been working great. It's a simple action with a single purpose... load a template with an internal value.
public function actionMyAction()
{
    $this->renderTemplate('myplugin/_mytemplate', array(
        'internalVar' => craft()->myPlugin->internalVar
    ));
}

When I call that action via a simple URL, everything loads flawlessly:

mywebsite.com/actions/myPlugin/myAction

Here's where it gets interesting...
So I just discovered the registerSiteRoutes hook. It looks awesome, and would make accessing my special page that much easier for a front-end user!
Here's how I implemented it in my MyPluginPlugin.php file:
public function registerSiteRoutes()
{
    return array(
        'myroute' => array('action' => 'myPlugin/myAction')
    );
}

The good news is, the route is properly followed, and my controller action gets loaded.
The bad news is, suddenly the template that's supposed to be loaded can't be found. :(

Template Error
Unable to find the template "myplugin/_mytemplate".

So does anyone know, what's going on here? I know that the renderTemplate method does some minor rewriting of the template path, but why would it be different when accessing via a front-end route?

Craft will only check for templates in your plugin’s templates/ folder during CP and action requests. When you start routing to your controller action via a site-facing route, it’s no longer either one of those; it’s just a normal Site request. So you will need to point Craft to your plugin’s templates folder explicitly.

// Point Craft to this plugin's templates/ folder
$templatesPath = craft()->path->getPluginsPath().'myplugin/templates/';
craft()->path->setTemplatesPath($templatesPath);

// Render and output the template
$this->renderTemplate('_mytemplate', $variables);

Note that it will no longer be necessary to include your plugin’s handle in the template path.


Sprout Forms: Map Element ID to Content Field on Save Entry Event What is the right way to save the entry id of a sprout form submission to a custom field in that form?

I've been fiddling with the SproutForms_EntriesService, but is that the completely wrong way to go about it?

This post was helpful, but the setContentFromPost threw errors for me. I've had success with getContent though:

$entry->getContent()->title = yourValue;

Still, I'm missing something:

Specifically, I've played with the saveEntry function, and I can save values before the event is validated (where the title is updated at line 156), but since I need the element ID, the value should be set after the entry has been successfully saved. But, if I move my code inside the successful new entry block at line 176, it's a dud:

Starting @176

// Now that we have an element ID, save it on the other stuff
if ($isNewEntry)
{
$entryRecord->id = $entry->id;
  // my crappy code:
  $entryId = $entry->id;
  $entry->getContent()->formEntryId = $entryId;
  // end crappy code
}

I could be going about this totally wrong. You'll have to forgive the ignorance; I'm a Front End Dev with general Craft skills who's delving into plugin dev for the first time. So, I'm at the beginning, studying the Craft Plugin Mijingo Course and just straight up reading through plugin files…

Thanks for your help!

L

You're almost there, as you can see on the SproutForms_EntriesService Class at line 197 we add a SproutForms_OnSaveEntryEvent. When this event is fired you can get the form entry submitted within the param 'entry'. All you need to do is add a listener to catch this event, please go ahead and add the following code to the init() function of the plugin of your custom field type:

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

        // Let's assume that your field handle is "custom"
        $entry->setContentFromPost(array(
            'custom' => $entry->id,
            )
        );
        // save it again. (avoid an infinite loop using sproutForms()->entries->saveEntry)
        craft()->elements->saveElement($entry);
    });


Plugin uploads an asset, need the final url I have a plugin which

uploads one or more files
creates a new entry with those files as new assets in a subfolder whose name is the new entry's slug
sends e-mail which includes links to the new assets.

The problem I have is that the url for the new assets is not their final url (in the subfolder), but /cpresources/tempassets/field_###/filename

The relevant bit of code:

if (craft()->entries->saveEntry($entry))
{
  // send the e-mail
  ... here when I send the e-mail, the url is wrong ...
}

What do I need to do after the saveEntry?

I think your best bet here would be to make use of the entries.onSaveEntry event, because at the moment $entry doesn't relate to the entry you have just saved, but the entry you wanted to save so it makes sense the entry asset paths are still pointing to the temp locations.

As far as i'm aware craft()->entries->saveEntry() just returns a bool, whether or not the save was a success, and not the entry model that was just saved.

So your controller could look like this:

if (!craft()->entries->saveEntry($entry))
{
 // Only worry if something goes wrong
}

Then in an init function in your main plugin class you could do something like:

craft()->on('entries.saveEntry', function(Event $event){

 // Is this a new entry?
 if($event->params['isNewEntry'])
 {
    // This is an EntryModel object of the entry that was just saved
    $entry = $event->params['entry'];

    // Is the entry in the right section?
    if($entry->sectionId == 1)
    {
      // Send the $entry to your email function
      craft()->yourPlugin->sendEmail($entry);
    }
 }

});

I would assume at this point the asset paths are all correct as it would have been saved to the database and all the backend work done etc

This would help you out in the future as well as it wouldn't matter where the entry was created, whether in the admin or through your plugin or anywhere else, and you could be sure the email will still get triggered :)

Failing that you could also try the assets.onSaveAsset event and see if you get better results with that?

http://buildwithcraft.com/docs/plugins/events-reference

I hope this helps in some way!


Sprout Email - accessing custom fields I'd like to set up a notification if an entry is saved in a the section 'memberNewsFeed'. The data that I would like to access is the entry title and url, and the user who made the change.

Can anybody advise of the syntax to input into rich text field that comes as standard with sprout email please?

You can access the dynamic variables in your custom fields using single curly brace syntax:

Title: {title}
URL: {url}
Author Name: {author.fullName}
Author Email: {author.email}

There is a longer discussion on Dynamic Values in the docs.


Displaying errors on frontend user forms I'm trying to get some feedback for the user on registration when the username already exists but I don't know in which object the errors are.

I use the form they provide in the docs:
https://docs.craftcms.com/v3/dev/examples/user-registration-form.html

Same for the forgot password form if the user doesn't exists in the system, I'm not able the provide the right feedback with this form:
https://docs.craftcms.com/v3/dev/examples/forgot-password-form.html

I just tested this with the user registration for in your link and got the expected behavior when you try to register with a username that already exists.

A few things to check.

Make sure you have public registration enabled in the Control Panel under Settings->Users->Settings.
When you're testing registering a user in your front-end form, make sure you're logged out of your current user account.


Plugin Installation Error in Craft 3 / PHP Version I tried to install "Field Manager" Plugin and get following error:

symfony/console v3.4.4 requires php ^5.5.9|>=7.0.8 -> your PHP version (7.2.1) overridden by "config.platform.php" version (7.0) does not satisfy that requirement.

Theres is no config.platform.php anywhere and i have PHP 7.2.1 installed. How can i fix that?

EDIT:
Ok, config.platform.php refers to composer.json entry. I changed it to 7.2 and could install it via command line. Possibly worked via CP too.

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

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

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


Getting environmental variable via plugin A similar question was answered before, but I was wonder how I might be able to return the same query from within a plugin (php)?

Convert this:

{{ craft.config.environmentVariables.baseUrl }}

To something like this: (not correct)

return craft()->config->get('environmentVariables.baseUrl');

What would be the correct syntax?

Thanks, Mark.

Solution:

return craft()->config->get('environmentVariables')['baseUrl'];


What would be the best way to build an Ad rotator? What would be the best way to build an Ad rotator similar to those we usually see around from http://fusionads.net for example.

WordPress have a plugin/widget for adding ads: https://wordpress.org/plugins/ad-rotator/

Basically it shows random HTML code every time you refresh the page.

I was wondering how we can do that with Craft.

I built a plugin which does exactly this... Ad Wizard.

You can put your ads into groups, and add that group to your template like this:

{{ craft.adWizard.position('rightSidebar') }}

That code will automatically display a random ad from the group (unless it's disabled, expired, or over its maximum allowed impressions).

You can also target a single ad specifically, by referring to its ID number:

{{ craft.adWizard.ad(42) }}

The plugin also gives you built in ad tracking... You can add two chart widgets to your dashboard which will show you statistics on how your ads are doing.

If you need any help, feel free to contact support@doublesecretagency.com... All feedback, bug reports, and feature requests are welcome!


Uploading assets to different locations based on environment I'm currently working on a new Craft CMS website for my company. We're using Elastic Beanstalk for hosting, which means that saving assets to file on the server isn't really viable- they get overwritten by code deployments- so I'm planning to have them saved to S3.

However when I or other developers are working on the site locally, uploading to S3 is both unnecessary and difficult (the company handles a lot of sensitive data so individual access to any of our AWS services is heavily ring-fenced). It would be preferable in development to just upload images to file locally and keep them out of version control.

Ideally I'd like to be able to change the root asset location depending on the environment. I've done similar things in Rails and Express apps, but am very new to Craft and PHP in general and am not sure where to begin. The official AWS integration seems to assume that you want everything going into S3 all the time. Does anyone have any experience of using different upload locations for different environments?

AFAIK, you can't change the type of your volume based on your environment. But if having a separate S3 account/bucket for dev could work for you, you can configure this with a volume.php config file. Check out this section in the docs about configuration for the gist on how to use it, and the section about per environment configuration in the readme for the AWS-S3 plugin for the specifics for that type of volume.


Craft Commerce: Sub total before tax in cart? I'm looking to get the sub total of all items in the car before and tax is added on. The example shop code doesn't seem to have this implemented. Is it possible to do?

  Total Discount: {{ cart.totalDiscount|currency(cart.currency) }}

  Total Shipping: {{ cart.totalShippingCost|currency(cart.currency) }}

  Total Tax: {{ cart.totalTax|currency(cart.currency) }}

  Total Tax (inc): {{ cart.totalTaxIncluded|currency(cart.currency) }}

  Item Total: {{ cart.itemTotal|currency(cart.currency) }}

  Base Discount: {{ cart.baseDiscount|currency(cart.currency) }}

  Base Shipping Cost: {{ cart.baseShippingCost|currency(cart.currency) }}

As of Commerce 1.1.1212, cart.itemSubtotalWithSale is deprecated.

Use {{ cart.itemSubtotal|currency(cart.currency) }} instead.

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


Upload failed for 'image.jpg' I tried to upload an image in the backend, but I always get the error: Upload failed for 'image.jpg'. In the logs is this:

[16-Jul-2015 21:33:48 UTC] PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 4966029 bytes) in /var/www/virtual/conwave/html/service/cgk/craft/app/vendor/imagine/imagine/lib/Imagine/Image/Metadata/ExifMetadataReader.php on line 72

Can anybody help me? I have no idea what the problem is.

Thanks!

You're running out of PHP memory as it's processes the image when it's uploaded. The fix for this is to increase the memory limit, which you normally need to get your hosting company to do for you. Try 512mb.


Use global values in the Entry URL Format field I'm trying to use global variables in Entry URLs generated by Craft, but they seem to be empty. Not getting any errors as such, just null.

My Entry URL format looks like this:

{{siteDefaults.artworksList.first.uri|default}}/{slug}

Where artworkList is an entry with a URI/URL but I'm getting "/some-entry-slug"

Similarly, {{siteDefaults.artworksList.length}} returns 0 even though there is an entry there.

Has anyone tried to use globals before in entry URLs?

Thanks!

Your CraftCMS global can be accessed using the code

{{craft.globals.getSetByHandle('siteDefaults').artworksList.first.uri|default}}/{slug}

I believe the issue is that the Entry URL field requires you to use craft.globals to prevent issues with the routing custom variables.


how to includeJsFile in head instead of body I am using this code to include a js file, but it adds to the <body>:

{% includeJsFile '/path/script.min.js' %}

I need to add it to the <head> instead, how can I do?

You can use the getFootHtml function to tell Craft where to output HTML queued up with includeJsFile and includeJs. You'd normally have that tag somewhere at the end of your <body>. But all it does is to get all queued up HTML and output it, so if your JS are already "included", you can use it in <head>.

Another thing you could do is to not use the includeJsFile function to add the HTML to the <head>, but use a different approach. Here's an example using a var and an example using a dedicated Twig block:

index.html

{% extends 'base.html' %}

{% set headHtml = '<script src="{{ url('assets/javascripts/myscript.js') }}"></script>' %}

{% block head %}
    {{ parent() }}

    <!-- Scripts -->
    <script src="{{ url('assets/javascripts/myscript.js') }}"></script>
{% endblock %}

base.html

<head>
    {% block head %}
        <!-- Document head -->
        <meta charset="utf-8">

        {% if headHtml is defined %}
            <!-- Scripts -->
            {{ headHtml }}
        {% endif %}
    {% endblock %}
</head>