Create new users with front end form and put them in a group, need help with start-elevated-session

Elevated sessions are basically user sessions where the user has proven to Craft that it’s really them within the last 5 minutes. It’s used whenever Craft is about to increase permissions on a user (either directly or via a user group).

The point of the concept is to reduce the chances of malicious permission escalation.

(In English, that means if a user with certain permissions/groups walks away from their computer, elevated sessions reduces the likelihood that another user could walk up to it, find their own user account, and increase their account permissions. They’d think they’re going to get away with it right up until the point where Craft asks them to re-enter their password, which kicks off the elevated session.)

I’m explaining this so that you understand the risk in what I’m about to say.

Maybe the easiest way for you to work around this issue is to just disable elevated sessions on your site. You can do that by opening config/general.php and adding this:

return [
    'elevatedSessionDuration' => 0,
    // ...
];

If you do that, Craft will no longer require elevated sessions anywhere.

Otherwise, you need to have the user enter their current password as part of the user form, and send that off to Craft’s users/start-elevated-session action.

You can get that action URL, and the CSRF token needed to make any POST requests to Craft, and send them to JavaScript like this:

<script>
    window.startElevatedSessionUrl = "{{ actionUrl('users/start-elevated-session')|e('js')|raw }}";
    window.csrfTokenValue = "{{ craft.app.request.csrfToken|e('js')|raw }}";
</script>

Then in JavaScript (assuming you’re using jQuery),

$.ajax({
    url: window.startElevatedSessionUrl, {
    type: 'POST',
    dataType: 'json',
    headers: {
        'X-CSRF-Token': window.csrfTokenValue
    },
    data: {
        password: $('#current-password-input').val()
    },
    success: function(response, textStatus) {
        // submit the user form...
    }),
    error: function(jqXHR, textStatus) {
        // error handling...
    })
});

If you want to get even fancier you can check to make sure the user doesn’t already have an elevated session by running a POST request to users/get-elevated-session-timeout. If response.timeout is greater than 5 (seconds) or so, then it’s safe to submit the form without prompting them for their current password.


SQLSTATE[42S02]: Base table or view not found

I solved the problem by setting up a new installation and then importing my backup database into that new installation. Now everything is there again and works.

I must admit I haven't found the reason why this problem occurred. But the solution was ultimately quick and easy.


Checking which version of Craft CMS a site is using

Looking via the FTP it appears that both Craft 3 and Craft 2 versions are installed in the vendors directory.

Craft 2 didn't use Composer, so wouldn't have a root vendor directory, so you're likely running some version of Craft 3.

Like Oli mentioned, if you can connect to the database, you can check the version column of the info table to see what version of Craft the site using.

If you can't access Craft's control panel, but can access the database, you can use this to gain control panel access: https://craftcms.stackexchange.com/a/13966/57


You're very close. Change "set tag" to "set tags" so you have:

{% set tags = entry.projektart %}

And then loop through the tags:

{% for tag in tags %}
    {{ tag }}
{% else %}
    No tags found
{% endfor %}

You could also simplify this and instead of setting the "tags" variable you could write the following:

{% for tag in entry.projektart %}


Get all entries with linked entry in entries field

Have you read the docs about relations?

'criteria' => [
    'section' => 'projects',
    'test' => 'testValue'
    'relatedTo' => id
]

Just replace id with the ID of your element

If you want to filter a specific field you have to include it as an array

'relatedTo' => [
    'sourceElement' => id,
    'field' => 'fieldHandle'
]


Filter Entries field by category in the CP?

No, this is currently not possible, but there's a feature request on Craft's feedback site
that you could vote for: "Entry Type" setting for Entries fields.

As Lewis Jenkins mentioned there, you could use his plugin Dynamic Fields as
a workaround solution in the meantime. Something like this should give you a dropdown field with
all "myOtherChannel" entries related to a category "myCategory".

{% set category = craft.categories.group('myCategoryGroup').slug('myCategory') %}
{% set entries = craft.entries.section('myOtherChannel').relatedTo(category).order('title asc') %}

{% for entry in entries %}
    { "value": "{{ entry.id }}", "label": "{{ entry.title|raw }}" }
    {% if not loop.last %}, {% endif %}
{% endfor %}


Plugin Development: find source group used by field

From the FieldModel you need to get the FieldTypeModel and then its settings. Something like this:

$settings = $field–>getFieldType()->getSettings();


Trouble with transliteration in slug caused by hardcoded charmap in craft.js

You can try using my plugin, which will overwrite the character map in craft.js by applying the customAsciiCharMappings setting:

https://github.com/farmstudio/slugcharmap

Tell me if it's working for you.


Error executing "ListObjects" on "https://franklin.ams3.cdn.digitaloceanspaces.com/?prefix=tools%2Finnovation-assessment%2F&delimiter=%2F&encoding-type=url"; AWS HTTP error: Client error: GET https://franklin.ams3.cdn.digitaloceanspaces.com/?prefix=tools%2Finnovation-assessment%2F&delimiter=%2F&encoding-type=url resulted in a 403 Forbidden response:

That's an AWS error, so I'm guessing you're trying to save the output to an S3 bucket, but the credentials you've configured the S3 buck with does not have "ListObjects" permissions on the bucket.


Entries retain field data that has been removed from entry type layout

Technically, all entries have all fields, regardless of their layout. Field layouts are mostly just a UI thing.

  1) Is there a way to tell if an field is actually actively assigned to the entry layout?

It’s a little cumbersome and would require the MN Break and Continue plugin, but yes:

{% for flf in entry.getFieldLayout().getFields() %}
    {% set field = flf.getField() %}

    {% if field.handle == 'text' %}
        {{ entry.text }}
        {% break %}
    {% elseif field.handle == 'multiContent' %}
        {{ entry.multiContent.text }}
        {% break %}
    {% endif %}
{% endfor %}

  2) I understand why the field data would be retained in the database even though the field was removed from the layout, but under what circumstances would populating 'deleted' fields for entries be desired behavior? It surely adds overhead, it is counter-intuitive (imo) and has the potential to cause all sort of issues.

Actually it’s faster for Craft to not worry about the field layout, which is why it’s not taken into account right now. Less data to fetch, and logic to run. If you check for entry.text, Craft just assumes you know what you’re doing.

Maybe a better approach would be to just check the entry type’s ID/name:

{% if entry.typeId in [1,2,3] %}
    {{ entry.text }}
{% elseif entry.typeId in [4,5,6] %}
    {{ entry.multiContent.text }}
{% endif %}

(or)

{% if entry.type.handle in ['one', 'two', 'three'] %}
    {{ entry.text }}
{% elseif entry.type.handle in ['four', 'five', 'six'] %}
    {{ entry.multiContent.text }}
{% endif %}


You can access children through the entry's descendants property.

{# display event-information #}

{{ entry.title }}
    {# display subsections #}

            {% for subsection in entry.descendants %}

{{ subsection.title }}

            {% endfor %}

You can also use the nav tag, as described in the documentation.

    {% nav entry in entries %}

            {{ entry.title }}
            {% ifchildren %}

                    {% children %}

            {% endifchildren %}

    {% endnav %}

More generally speaking, you can use any of the following properties of the EntryModel to traverse the structure: parent, children, descendants, ancestors, siblings, nextSibling, prevSibling, and level.


Issue accessing single entry from within category template

Okay, solved.

Was an idiot and wasn't using the right tag to output the results of the query.

Sorry and thanks!


How do I add the Categories and tags related to each entry?

Supposing your categories and tags fields are named, respectively, newsCategories and newsTags, you could do the following for the categories:

{% for category in entry.newsCategories %}
    {{ category.title }}
    {% if not loop.last %},{% endif %}
{% endfor %}

And for the tags:

{% for tag in entry.newsTags %}
    {{ tag.title }}
    {% if not loop.last %},{% endif %}
{% endfor %}

This code is untested, but I think this should more or less do what you want to achieve.


Easy way to stage template updates for a live site

There is a PHP Constant CRAFT_TEMPLATES_PATH which you can use to specify your Template Path. Would that help you out any?

If you look at the top of the page linked above, it explains where you set the Constants.


Sorry, false alarm. My template file was not syncing with the server. To recap, this works like a charm:

{{ redirectInput('join/payment/{id}') }}

This results in a redirect that includes the ID of the entry or user that was just created!


What's the trick to importing an entry with a categories field?

It's the modifyImportRow hook. If one uses that sample code in the Read Me, related categories will not import.

So we will have to run at least two imports, one with our Import Helper that uses the hook enabled  (for tables, booleans, dates, etc.), and one without, in order to append the related categories.

Unless someone can provide better example code to exclude an entry category field, but I can't think of how right now.


If I understand your question well, you need to use the EVENT_REGISTER_TABLE_ATTRIBUTES event. This thread should get you on your way :)


Not currently, but not a bad idea.  I'll add it to the list.


You could loop through all your events, and create a date-keyed hash with the ids of the entries - assuming your  (e.g

    {% set saleDays = {} %}
    {% for entry in events %}
       {% for row in table %}
          {% if attribute(saleDays, row.date|date(mdY)) is defined %}
               {% set saleDays = saleDays|merge({
                  (row.date|date(mdY)): attribute(saleDays, row.date|date(mdY)) | merge([entry.id])
               }) %}
          {% else %}
               {% set saleDays = saleDays|merge({ (row.date|date(mdY)): [entry.id]})
          {% endif %}
     {% endfor %}

This would result in a hash, whose keys were dates of ticket sales, and whose values were arrays of entry id's (which could then be queried), or you could set the values inside the array to the entry models themselves.

You would then need to sort this hash to get the dates in order (think you'd need to write a custom extension), and then you could loop through it.

But to be honest, by that point you'd be better off just writing a module and doing the whole thing in php where it'd be easier.


Is the length filter required when checking if a field has content or not?

You can probably get away with removing |length for most conditionals that check for the existence of content in a custom field and just check on entry.fieldHandle instead.

One exception to this would be for lightswitch fields, which always return true for a |length check, but return true or false when checking on entry.fieldHandle depending on whether the lightswitch is on or off.

StraightUpCraft has a great article on Testing if something exists and another on How to check if a variable or value exists using Twig, which cover a multitude of cases and ways of accessing variables using Twig.


Where do you all host your CratCMS sites?

Anything that you can config and auto-deploy through using https://forge.laravel.com/ (Digital Ocean, Rackspace, Amazon).


Has anybody integrated craft with a rewards system?

I don't think there's a plugin, but there's numerous jQuery or SaaS products that achieve this.

For a Craft Plugin, you could hook onto the after purchase event and add a set amount of score to a user field.

e.g. if our field was score, after purchase we could add +30 to the score field. Then assign discounts based on the score field. e.g. if $score > 30 assign 30% discount to products.

For integrations, you could easily just listen for the event and send some data via a PUT request to a third-party system.


getting fields of a section (getFields())

You don't need to go through craft.fields to get the fields. They are already there.

{% set fields = craft.entries.section('rentalsBulletin').getEntryTypes().first.getFieldLayout().getFields() %}
{% for field in fields %}
    {% set type = field.getField().type %}
    {% include 'rentals-bulletin/_components/form-field-types/' ~ type %}
{% endfor %}

You will probably also want to pass some variables into your included templates to actually build the fields with the proper field names as well.

{% set properties = { 'name': field.getField().handle } %}
{% include 'rentals-bulletin/_components/form-field-types/' ~ type with properties %}

There are also a few plugins available on the plugins page for form building that you might want to check out.

Update Looks like craft.entries.section('rentalsBulletin').getEntryTypes() returns null when there are no entries defined. Instead you can go through a different route that doesn't seem to depend on entries.

{% set fields = craft.sections.getSectionByHandle('news').getEntryTypes()[0].getFieldLayout().getFields() %}


Omit Featured Entry from loop of entries with additional omissions

My variable wasn't outputting the id and it wasn't being pulled into my omitIds variable

{% set featuredIds = entry.featuredEntry.first.id %}

{% set omitIds = 'and, not ' ~ taggedEntries|join(', not ') ~ allEntries|join(', not ' ~ featuredIds) %}

Adding .first.id to my entry.featuredEntry outputs the correct id.
Then removed featuredIds from the ', not ' in omitIds and added ~ featuredIds pulls in the correct id and omits it from the list.

Feel free to edit as I'm sure I'm not explaining this correctly.


You can delete that folder entirely and it will get re-created on the next request that needs a template.

If it's not updating, chances are you've got some PHP byte-level caching extension installed like APC or OPcache that's not busting cache properly.


How to get submitted data in Sprout Forms custom email

Following Sprout Forms example templates (/admin/sproutemail/settings/examples): in your email.html file Hi {{ object['yourName'] }} or even Hi {{ object.yourName }}, should print Hi Bob.


This question comes close but implementing with a subdomain doesn't work.

It should work as long as you modify the rewrite rule to account for the subdomain:

RewriteCond %{HTTP_HOST} !^foo\.bar\.com$ [NC]
RewriteRule ^(.*)$ http://foo.bar.com/$1 [R=301,L]

The code you posted was missing the ^ before foo\.bar\.com on the RewriteCond line. The purpose of that conditional is supposed to be to catch incoming requests where the domain isn’t exactly “foo.bar.com” (so that it can redirect them to the correct domain on the following line). However without that ^, the conditional would only catch requests where the domain doesn’t end with “foo.bar.com”.  But “www.foo.bar.com” does in fact end with “foo.bar.com” so it’s not going to get caught.

Hope that makes sense.

Update:

Here’s a hostname-agnostic version that’s a little easier on the eyes:

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


Would you use a Structure as navigation over multiple sections (channel entries, indexes and singles)?

Structure for "sorting-only"

I haven't tried the approach that you are thinking of yet, but your concerns regarding the query count are not that unfounded. You would need to use the relatedTo() parameter with the ElementCriteriaModel you create on your pages (to get the single's content)
on your navigation include (even if you only want to get the entries URL) and relations can have a rather big performance hit. Hopefully this is not true for a simple relation like this; otherwise, you'd still have the cache tag. But I'd suggest you to cache the whole include (this is a perfect example for caching being really useful). Additionally setting the limit to '1' will probably help to keep the query count low if the cache is cleared.

{% cache for 3 years %}

    {% set pages = craft.entries.section('pagesSectionHandle').level(1) %}

    {% for page in pages %}

        {% set params = {
            relatedTo: { sourceElement: page, field: "entriesFieldHandle" },
            limit: '1'
        } %}

        {% set linkedEntry = craft.entries(params).first() %}

        {# Get the title from the structure (why set this twice?) #}
        {{ page.title }}

        {# Get the title from the entry #}
        {{ linkedEntry.title }}

    {% endfor %}

{% endcache %}

Structure containing "all the content"

What I'd suggest you to do is to not only use the structure as a "sorting only" structure, but to also add content directly to it.

Use entry types for your singles, if you need to load individual templates for them, and further entry types for your channel index pages. If it's thought-out carefully (modular site design) you probably won't end up with lots of entry types.

Combining those two

If you have a need to link to specific channel entries from your navigation, you could make an entry type in your structure specifically for those links to channel entries. All other content could still be added directly to the structure itself as described above.

I think that being able to edit the content directly in the pages structure is a very convenient and less geeky like experience for the client.

Edit:

This is what Naboovalley and I came up with in the chat (we should have done this before spamming the comments section). It "will give you a fully dynamic menu for your client linking between Singles, Channels and even other Structure entries":

{% cache globally for 3 years %}
{% set entries = craft.entries.section('navigation') %}

    {% nav entry in entries %}

            {# Check for entry type / get related entry #}
            {% if entry.type == 'linkedChannelEntry' %}
                {% set linkedEntry = entry.entriesField.limit(1).first() %}
            {% endif %}

            {% if linkedEntry %}

                {# Link to a linked channel entry #}
                {{ linkedEntry.title }}

            {% else %}

                {# Link to a structure entry #}
                {{ entry.title }}

            {% endif %}

            {# Repeat this for child entries #}
            {% ifchildren %}

{% children %}

            {% endifchildren %}

    {% endnav %}

{% endcache %}


Listing Sub Categories of a Category related to an entry

Check out the documentation for craft.categories which should do what you need. In this example, I assume that 'landing pages' are the same as your level 1 categories, in which case you don't need to deal with the entries at all:

{% set categories = craft.categories.group('navCategories') %}

    {# using 'nav' and 'children' will create a recursive loop #}
    {% nav category in categories %}

            {% if category.level == 1 %}
                {{ category.title }}
            {% else %}
                {{ category.title }}
            {% endif %}
            {% ifchildren %}

                        {% children %}

            {% endifchildren %}

    {% endnav %}

If you only want a certain number of levels then you can use a level filter. I.e:

{% set categories = craft.categories.group('navCategories').level('< 3') %}

Update: If level 1 categories are not the same as your landing pages then you can access the category through entry.category.first, and then category decendants using: {% for category in category.descendants %}...{% endfor %} or {% nav category in category.descendants %}...{% endnav %} using the recursive method above.

    {% set entries = craft.entries.section('landingPages') %}
    {% for entry in entries %}
        {% set category = entry.category.first %}

            {{ entry.title }}

                {# using 'nav' and 'children' will create a recursive loop, if more levels are needed #}
                {% nav category in category.descendants %}

                        {{ category.title }}
                        {% ifchildren %}

                                {% children %}

                        {% endifchildren %}

                {% endnav %}

    {% endfor %}

As a side-note: Keep in mind that you can also define css dynamically within the loop rather than defining it on the elements directly, if you wanted to.

{% set css %}
    a.{{ category.slug }} {
        border-color: {{ category.supplierColour }};
        color:{{ category.supplierColour }};
    }
{% endset %}
{% includeCss css %}


Way to getNext() within the same category

You're close! getNext and getPrev take an ElementCriteriaModel as a parameter:

{% set params = craft.entries.section('news').relatedTo(category) %}

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

{% if prevEntry %}Previous{% endif %}
{% if nextEntry %}Next{% endif %}

Or, if you prefer, a params array (same as you would pass to craft.entries ElementCriteriaModel):

{% set params = {
    section: 'news',
    relatedTo: category,
} %}


You can try this

<IfModule mod_rewrite.c>

    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

    # Send would-be 404 requests to Craft
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

    RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]

    RewriteRule ^/outdoor-furniture/all-garden-benches /outdoor-furniture/garden-benches [NC,L,R=301]

    RewriteRule (.+) index.php?p=$1 [QSA,L]

</IfModule>

If that doesn't work you can always try using a plugin for your redirects

https://plugins.craftcms.com/redirect
https://plugins.craftcms.com/retour


Registration into default group is not working as expected

I get bit by this a lot.
Just like @Stephen Lewis suggested - make sure you are not logged into the same browser.

For example, log into the CP with Safari (or whatever) and then use Chrome to actually register an account via your front-end form.


Where are Matrix Entries Fields Relationships in the Database?

I think I've figured it out. The sourceId of the craft_relations table is the elementId of the custom matrix table. And the targetId of the craft_content table is the elementId of the `craft_content table.

Code example

Here's what I was trying to do. I needed to filter entries based on a field value in an Entries matrix field on another entry. Whew.

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

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

$query->join('matrixblocks matrixblocks', 'matrixblocks.ownerId = entries.id');
$query->join('matrixcontent_MYMATRIX matrixcontent_MYMATRIX', 'matrixcontent_MYMATRIX.elementId = matrixblocks.id');
$query->join('relations relations', 'relations.sourceId = matrixcontent_MYMATRIX.elementId');
$query->join('content SECONDCOOLTHING', 'SECONDCOOLTHING.elementId = relations.targetId');

$query->andWhere('SECONDCOOLTHING.field_FIELDHANDLE = '.$THINGTOSEARCHFOR);

$query->order('title asc');

$queryResults = $query->queryAll();
return EntryModel::populateModels($queryResults);


Setting structure section entry titles dynamically based on the entry level

I resolved the issue by using the following code for my title format

{% if object.parent %}{ postDate|date('M') }{% else %}{ postDate|date('Y') }{% endif %}


How do I allow a user to remove an uploaded asset from a front-end entry form?

File fields are used for uploading new images. To delete all the Assets for a field, submit a hidden field with no values.

<input type="hidden" name="fields[assetsField]" value="" />

If, on the other hand, you want to retain some of them, then make that hidden field an array with the values you'd like to keep. Like this

<input type="hidden" name="fields[assetsField][]" value="someAssetId" />
<input type="hidden" name="fields[assetsField][]" value="someOtherAssetId" />

someAssetId and someOtherAssetId being the Asset IDs you'd like to keep for that field.


It turns out the cache-control headers weren't coming through at the end.
I solved the problem by adding all the right headers.
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "Wed, 12 Jan 1980 05:00:00 GMT"


How to set Home page menu as active when slug is not defined in admin panel?

craft.request is useful for setting an "active" class based on URL segments without slug.
In your template you can set a slug in twig and then you can run if statement to check what the segment is. Check below example for that.

    {% set slug = craft.app.request.getSegment(1) %}
    {% for entry in entries %}
        {% set destination = entry.linkDestination.one() %}

            {{ entry.linkText }}

    {% endfor %}


Adding new matrix block will result in wrong locale

This is a UI bug when saving a new Matrix block in an new entry.

If you save, the data is saved into the correct locale and the fields in Matrix blocks will display their correct locales (in your case sv).


Updating plugin to Craft 3: craft()->urlManager->setRouteVariables?

Craft::$app->getUrlManager()->setRouteParams(['calupdateResponse' => $out]);

All Components should be treated as singletons, don't create a new instance of them

Note: you can also do

Craft::$app->urlManager->setRouteParams(['calupdateResponse' => $out]);

But it is considered as bad practice

Edit: most parts of Craft 3 are working with Craft 2 as well... craft() is just a mapper for Craft::$app


Can't find the "share entry" functionality

The arrow is the Share button. If it’s just opening Live Preview for you, please get in touch with us directly – support@buildwithcraft.com.


How to build a language switcher that covers entries with custom routes?

Here's how I did it with a macro and some custom entry IDs.

In the basic template

{# Set PIDs for important pages #}
{% set pidNews = 214 %}
{% set pidPressReleases = 208 %}
{% set pidAgenda = 224 %}
{% set pidJobs = 227 %}

{# Section Ids #}

{% set sectionIdPages = 1 %}
{% set sectionIdNews = 2 %}
{% set sectionIdEvents = 3 %}
{% set sectionIdJobs = 6 %}

{# Type Ids #}

{% set typeIdNews = 2 %}
{% set typeIdPressReleases = 14 %}

In the Langswitcher partial

{# Detail views with special routes (news,jobs,events): generate the path by hand #}
{% macro getTranslatedLink(parentPageId, entry, site, currentSite, otherUrl, loop) %}
  {% set otherEntry = craft.entries.id(entry.id).site(site).one() %}
    {% if otherEntry %}
      {% set otherSlug = otherEntry.uri %}
        {% if parentPageId %}
        {% set otherParentPageUrl = craft.entries.section('pages').site(site).id(parentPageId).one().getUrl() %}
        {% set otherUrl = otherParentPageUrl ~ '/' ~ otherSlug %}
        {% else %}
          {% set otherUrl = otherEntry.getUrl() %}
        {% endif %}
    {% endif %}
    {# return the link #}
    {{ site.name }}{{ loop.last ? '' : '|'}}
{% endmacro %}

  {% for site in currentSite.group.sites %}

      {# Set fallback value #}
      {% set otherUrl = alias(site.baseUrl) %}
      {% if entry is defined %}
        {% switch entry.sectionId %}
        {# Construct the URLs for news/mm, events, jobs detail pages #}
        {# News #}
        {% case sectionIdNews %}
          {# Press Releases #}
          {% if entry.typeId == typeIdPressReleases %}
          {{ _self.getTranslatedLink(pidPressReleases, entry, site, currentSite, otherUrl, loop) }}
          {# News #}
          {% else %}
            {{ _self.getTranslatedLink(pidNews, entry, site, currentSite, otherUrl, loop) }}
          {% endif %}
        {% case sectionIdEvents %}
          {{ _self.getTranslatedLink(pidNews, entry, site, currentSite, otherUrl, loop) }}
        {% case sectionIdJobs %}
          {{ _self.getTranslatedLink( pidJobs,entry, site, currentSite, otherUrl, loop) }}
        {# Pages #}
        {% default %}
          {{ _self.getTranslatedLink(null, entry, site, currentSite, otherUrl, loop) }}
      {% endswitch %}
      {% endif %} {# end: if entry is defined #}

  {% endfor %}

It's not extremely elegant, but it's flexible and it apparently works. So I thought I'd share it.


How to Use defineAttributes To Specify NOT NULL and DEFAULT '1' in MySQL Record

For NOT NULL use 'required' => true and to default to 1 use 'default' => 1.


Of course as soon as I post this, I find the answer.

  /app/etc/config/defaults/general.php

  'defaultFilePermissions' => 0664,

  'defaultFolderPermissions' => 0775,

The default settings are there, I just need to add them to my own config.


Is it possible to have entries only visible to logged-in users?

Yes. You need to build a frontend login form and then block non logged in users from seeing the entries with something along the lines of this:

{% if craft.session.isLoggedIn %}
    {# put content here #}
{% endif %}

You can also check if the user belongs to a specific group with isInGroup('groupHandle') (more here)


Sorted, thanks. The keen-eyed of you will notice that there was a space character in the server connection details. Idiot


In Craft 3 it is actually possible.

{{ craft.app.view.evaluateDynamicContent('phpinfo();') }}

See: Can we use PHP in our templates instead of Twig?


I think you can just add .offset(3) to the "remaining" craft.entries query to get the result that you want. Or you could exclude the id's of the first three.

But, this is quite ineffective (performance wise), since you're doing four separate queries to get the entries. An alternative would be to loop over all, and use the loop object together with conditionals to build the output. Something like this:

{% for entry in craft.entries.section('shows') %}
    {% if loop.index==1 %}

                {% include "_partials/card" %}

AD

    {% elseif loop.index==2 %}

                {% include "_partials/card" %}

    {% elseif loop.index==3 %}

                {% include "_partials/card" %}

    {% elseif loop.index>3 %}
        {% if loop.index==4 %}

        {% endif %}

                {% include "_partials/card" %}

        {% if loop.index==loop.last %}

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


.all() returns a collection of elements, which you can loop through with a for loop.

.one() returns a single element, so you cannot use a for loop to access it.

In this case you should just store the entry like:

{% set entry = craft.entries.section('thing').one() %} and then access {{ entry.title }} afterwards.

(Also keep in mind that entry is automatically populated for section URLs, so you may want to use another variable name)


You'd do it from PHP nearly idential to how you'd do it from Twig... by passing in the Asset Transform's handle to AssetFileModel's getUrl() method.

Twig:

{% set asset = craft.assets.id(1).first() %}

{% if asset %}
    {{ asset.getUrl('myTransform') }}
{% endif %}

PHP:

$criteria = craft()->elements->getCriteria(ElementType::Asset);
$criteria->id = 1;
$asset = $criteria->first();

if ($asset)
{
    $url = $asset->getUrl('myTransform');
}


Object of class Craft\ElementCriteriaModel could not be converted to string

You'll want to use block.icon.first() if you just want the first Asset, or you could loop through all Assets:

{% for block in entry.visitorContentBuilder %}

    {% if block.type == "listItemWithIcon" %}

        <ul>
            {% for icon in block.icon %}
                <li>{{ icon }}
            {% endfor %}
        </ul>

    {% endif %}

{% endfor %}

See here for a description of the difference between an ElementCriteriaModel and actual fetched elements in Craft.


How do you rename a tag globally in the Craft Control Panel?

As of Craft 2.0 you can rename tags by double-clicking on them.


I want to be able that users can enter their emailaddress in an input and that the activation link gets resend

You'll need to write a plugin, which can generate activation URLs using the UsersService:

echo craft()->users->getPasswordResetUrl($user);

If you want to send the user an activation email instead of echoing a link in the frontend, you can use the sendActivationEmail method instead:

craft()->users->sendActivationEmail($user);

Note that for both methods, $user should be an instance of UserModel, meaning you'll first need to pull the relevant user:

$user = craft()->users->getUserByEmail($userEmail);

As for the actual plugin implementation, it depends what you need/want (I'm guessing you're building your own login form/logic?). You could go with a basic template variable to output the activation URL:

Click here to activate your account now

...or you could create a controller which would provide a link for re-sending the activation email:

Click to resend activation email


Conditional if statement for Matrix dropdown option

If I understand things correctly, you have a matrix block telephone, which contains a dropdown field telephone.icon, and you want the value of the selected dropdown option. That value is telephone.icon.value (which will be one of mobile, home, work, or other).

{% for telephone in user.profilePhone %}

    {% if telephone.icon.value == 'mobile' %}

    {% elseif telephone.icon.value == 'home' %}

    {% else %}

    {% endif %}

    {% if telephone.country %}{{ telephone.country }}{% endif %}
    {{ telephone.number }}

{% endfor %}


Can't Output Entries from Particular Blog Categories

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


How to iterate over matrix field from a plugin

So, first you want to get the entry model using your entry id. In the EntriesService there is a method called getEntryById which you can use like so:

$entry = craft()->entries->getEntryById(123);

This will return you an EntryModel which has on it all your fields. So, if you matrix field handle is called matrixFieldHandle then you would access the field contents like so:

$matrixBlocks = $entry->matrixFieldHandle;

A matrix field will return you an array of MatrixBlockModels from which you can get at everything else you need e.g.:

foreach ($matrixBlocks as $block){
  echo $block->id;
  echo $block->fieldHandle;
}

Note that to play with block types you will need to look at the MatrixService and getBlockTypeById() to do things like filter out different blocks based on their block types.


Create a custom field with my plugin data

The questions is a bit short on details but from what you've posted, it sounds like a custom field type is what you're looking for.


Why does my Twig for loop not get a Key?

I'm guessing that you'd like {{ categoryTitle }} to be the current groups documentType.title?

If so, I would output document.documentType for the first document in each group using {% if loop.first %}.

Complete code suggestion would be:

{% set grouped = entry.documents|group('documentType.first().title') %}

{% for groupedRows in grouped %}
  {% for document in groupedRows %}
    {% if loop.first %}
      {{ document.documentType }}
    {% endif %}
    {{ document.documentTitle }}
  {% endfor %}
{% endfor %}

EDIT: updated to use carlcs group filter suggestion.


How can I pass an array to an api call from my plugin?

You're right, this won't work— PHP doesn't know how to flatten an array into a URL param.

But! Guzzle has it's own way of collating multiple values for one param.

Basically, you build your query with Guzzle's API, then repeatedly add values to the same param with the getPostFields()->add() method.

# Note that the second argument below may need to be populated with your custom headers— but Guzzle may also take care of this when using this method…
$req = new \Guzzle\Http\Client('https://www.site.com/api/')->post('users', [], [
  'param' => 'val' # …and any other single-use keys can be set early
]);

foreach ( $selectedActivities as $option ) {
  $req->getPostFields()->add('param-name', $option->value);
}

I can't tell you how to visualize the URL this eventually builds, but I think the key is sending data in the body, rather than trying to manually build a query string (which still ought to work, but there are odd behaviors when duplicate params exist).


Doing something with the success response from a Webhook

You might want to look into creating a simple Craft plugin to do this. You can make the first call to add the contact and get the ID in response. Then use that ID to add to a campaign.

Do not be intimidated by plugin development, your problem is fairly easy to solve. If you are on Mac, I like the Paw app to test API calls.


What does the Before compile event inside the Contact Form plugin do?

How does one use this event? What can it be used for?

It gives plugins a chance to manipulate the posted message to however they want instead of using the plugin's default implementation.  A plugin would listen to it like they listen to any other event. Something like:

public function init()
{
    craft()->on('contactForm.onBeforeMessageCompile', function(Event $event) {
        $postedMessage = $event->params['postedMessage'];
        $event->messageFields = $postedMessage;

        // Do your thing.

        $event->message = "Your custom compiled message";
        $event->htmlMessage = "Your custom compiled HTML message";
    });
}

  Why is an $event object being instantiated at this point in the controller?

The short answer is "because that's how events work". :) Is there a particular thing that's confusing you?


Protect entry so that only a "relatedTo" user can see it

You could loop through the users and compare them.

{% set authorized = false %}
{% for user in entry.authorizedUsers %}
    {% if user == currentUser %}
        {% set authorized = true %}
    {% endif %}
{% endfor %}

{% if not authorized %}
    {% redirect 403 %}
{% endif %}


When uploading an asset, the asset is not selected after upload

We have quite a few assets, so there is auto pagination/load more which might be causing the issue?"

You nailed it. It's a known issue and we just haven't figured out a clean way to to select the items when they show up in a different page.

I'd suggest adding this to the feedback site as it feels more like a feature request than anything.


Installing happylager demo site on own server (not locally)

Thanks @BradBell , your comment made me recheck everything - i just forgot to take out the files from the public folder... now everything looks fine.


I ended up getting this great plugin called Redactor Extras
https://github.com/elliotlewis/Redactor-Extras

Installed easily, and it has a properties option that it adds to rich text fields that lets you add a class or id to a piece of text. I just add id=something and then link to #something. Works like a charm for adding anchors!


Public profile page: requesting user ID with dynamic url routing

.first() is going to be required... I updated the answer in the original question, but here it is for posterity, too:

{% set notWorkingUserId = craft.request.getSegment(2) %}
{% set notWorkingUser = craft.users.id(notWorkingUserId).first() %}

Then you can access the properties of that user because it's a proper UserModel now:

notWorkingUser.email


Counting section handle in TWIG with weighted search plugin

You can search each section separately, count the totals of each and then merge them back together to form your full results.

{# Search each section separately #}
{% set query = craft.request.getParam('query') %}
{% set mapMarkerResults = craft.weightedSearch.substringSearch(query, ['mapMarker']) %}
{% set blogResults = craft.weightedSearch.substringSearch(query, ['blog']) %}

{# Merge the two sections' results together #}
{% set fullResults = mapMarkerResults|merge(blogResults) %}

Because Twig's |merge filter will add all the blogResults after mapMarkerResults the sort order will be wrong. Using the SuperSort plugin (version 1.2.0 supports Craft 2) you can fix that.

{# Use SuperSort's rsortAs method to sort the results by Weighted Search's score in descending order #}
{% set fullResults = fullResults|supersort('rsortAs', '{score}') %}

Now you can handle the output.

There's {{ blogResults|length }} results from the Blog section.
There's {{ mapMarkerResults|length }} results from the Map Marker section.

{% for searchResult in fullResults %}
    {{ searchResult.title }}
{% endfor %}

Note: SuperSort might not sort exactly the same as Weighted Search. They will correctly be sorted by score in descending order, but it might not break ties the same way (e.g. two entries with a score of 1). If it's important for the search results to be in exactly the same order as Weighted Search you should run the search again. This is obviously more server intensive and I wouldn't recommend it as it'll slow down your page loads.

{% set mapMarkerResultsCount = craft.weightedSearch.substringSearch(query, ['mapMarker'])|length %}
{% set blogResultsCount = craft.weightedSearch.substringSearch(query, ['blog'])|length %}
{% set fullResults = craft.weightedSearch.substringSearch(query, ['people', 'blog']) %}


How do I print the number of entries assigned to a category?

You'll want to query for the number of entries inside the for loop.

{% for categoryName in craft.categories.group('markets') %}
    {% set numofEntries = craft.entries.section('posts').relatedTo(categoryName).total() %}

    {{ categoryName.title }}-{{numofEntries}}
{% endfor %}


Is it possible to skip Craft Installer through command line or something similar?

There are several ways you could approach this.  There is a bash script that automates downloading the latest version of Craft, but it doesn't do the actual installation.

What I would do is create a PHP script that used prompted to accept Craft's license agreement, then used cURL/wget to download and extract the files.  You could prompt for all the information you need for installation (username, password, database, database connection info, etc.), then the script would load Craft's craft/app/bootstrap.php and call Craft's InstallService->run() method passing in the necessary values similar to how Craft's craft/app/controller/InstallController does.


Prepping a field's value from a fieldtype before it hits Craft\BaseModel->__set()

I can see how this is unexpected behavior. The code in BaseElementModel::setContentFromPost() isn’t considering that the ContentModel it’s setting data to is going to be doing its own manipulation of the data before the field type has had a chance to tweak it (thanks to setAttribute()). And in AttributeType::DateTime’s case, that means trying to convert the value to a DateTime object, else completely discarding the value.

Anyway, I’ll tweak this for the next release. Shouldn’t have any negative side effects if we just hold off on assigning the value to the ContentModel until after the field type’s prepValueFromPost() has had a chance to do its thing.


How to search against a specific field/s, and not every field related to an element?

You can just limit your search to those specific user fields.
It should go something like:
{% set users = craft.users()
    .search('fullName:' ~ query ~ ' OR username:' ~ query)
    .group('creatives')
    .all() %}

More info on searching here: https://docs.craftcms.com/v3/searching.html#supported-syntaxes
Top tip: You can test your search query directly in the search bar within Craft's admin. e.g. See if fullName:Tom OR username:Tom pulls the intended results.


Adding a drop-down to Contact Form plugin

It's definitely possible, your HTML is just a little off...

When dealing with a dropdown menu, the name attribute should be part of the select tag, not each individual option:

<select name="message[model]">
  <option value="——" selected="selected">Please select...</option>
  <option value="volvo">Volvo</option>
  <option value="saab">Saab</option>
  <option value="mercedes">Mercedes</option>
  <option value="audi">Audi</option>
</select>


It's totally possible. However, since there is no existing plugins for this that is readily available, you'd have to create a custom plugin to do it.

If you have the necessary coding chops, you can get a flying start by generating the boilerplate over at pluginfactory.io.

If not, you can hire a programmer in the Craft community to do this for you. Posting in the Craft slack channel #jobs should get you started.


Image quality get low in Craft 3 after applying image transform

If the dimensions of the image are being displayed is larger than the transform dimensions it will show pixelation in the image. Just double up the dimensions of the transform image to see if this fixes it.


Search Results In a Drop List/Popup on Same Page

You can request any template via ajax using jQuery. jQuery would essentially listen for onChange events from the search field and ajax load a template that looped through the search results.

The template that you request can even be the default full search results page, with a conditional that determines which part of the template gets returned if the request is ajax.

{% set query = craft.request.getParam('q') %}
{% set entries = craft.entries.search(query).order('score') %}

{% if not craft.request.isAjax %}
    {# Full page results content can go here #}

Search Results

        {% for entry in entries %}

{{ entry.title }}

        {% endfor %}

{% endif %}

{% if craft.request.isAjax %}
    {# Drop-down results can go here. And inserted into DOM via jquery. #}
    {% for entry in entries %}

{{ entry.title }}

    {% endfor %}
{% endif %}

jQuery can then insert the results of the ajax call using an html element selector. See the jquery documentation for more information on using .load or .ajax.

You will also probably want to put the {% set entries ... %} inside the if isAjax statements so that you can limit the results, or implement pagination, for the drop down vs the full page.


Creating fields programmatically / with PlugIn

You can look at Craft's own InstallController and InstallService to see how Craft programmatically creates the default content you see during a fresh install.


Users are always logged out on front end

I tracked down a similar problem, and documented it here: The Case of the Missing PHP Session

I'm not sure if it'll address the issue you're having specifically, but it may give you some clue on where to look.


Just re-throw the exception and pretend like nothing ever happened...

try
{
    // Some code which might produce an error
}
catch (\Exception $e)
{
    if (craft()->request->isCpRequest()) {
        // Do something with $e->getMessage()
    } else {
        // Nothing to see here...
        throw $e;
    }
}


Live preview + share button missing when switching to PRO licence

I've seen something similar happen. I don't know the cause of it, but the solution in the 2 cases I know of each has the same fix. What happened was that for some reason, the "preview targets" got wiped out. In my case, this was during an update to the database. In another person's case that I know of, I think an upgrade was involved.

From within the control panel, go to "Settings -> Sections" then click the name of the section that is missing the preview buttons. Look at the bottom of the page and see what it says in the "Preview Targets" area. It should look something like this screenshot. If it doesn't add a new row and fill it in like the image shows.


Entries search without using asset fields

As suggested in this stack post, you could specify each field individually. I haven't done this with fields, but often do so with sections and entry types in global site searches. It is kind of annoying, but I'm not sure there is a way to do this using Craft's API.


Just tested your code and it worked as you'd expect if you leave off the extra getExtension() call (the filename property already includes the extension).

$filename = strtolower($asset->filename);

If it's not saving for you with that, you've got some other error happening elsewhere.


Unable to update slug in Craft 3 for single enteries

You have to change the URI format in your section for the specific language.

Go to settings -> sections -> your single section, there you'll have a table below and you can insert the URI format you like for every site.


Local and Staging Environments allow for updates, Live doesn't (and doesn't recognise the license.key)

The problem is that I had disabled a few PHP functions as part of a security tweak.... I'm assuming it's using cURL to make the request to phone home.


Updating an entry record programatically?

After you call $criteria->first(), you no longer have an ElementCriteriaModel, but an actual EntryModel, so probably more semantic to change to:

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'affiliates';
$criteria->limit = null;
$criteria -> search ='email:'.$email;
$entry = $criteria->first();

$entry->getContent()->setAttribute("optOut", "true");

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

But my guess about your actual problem is you're getting a validation error.  You can verify and guard against that in your code by doing something like:

if (craft()->entries->saveEntry($entry))
{
    return $entry->title;
}
else
{
    $errors = $entry->getErrors();
}


I want my custom field values to be stored on a per-locale basis, but can't seem to do this.

No, you're not doing anything wrong. Craft copies the content over to all the other locales when you save an entry for the first time.

The idea behind this is to give content editors a base for the translation, and for some content it’s not even necessary to translate at all. Imagine a text field for city names for example, you don’t need to translate "Berlin" or "New York" for some locales, but for "Berlin and Munich" the German translation would be "Berlin und München".

One feature you might not have discovered is the "Default Entry Status" setting in the section settings. If you disable a locale by default, Craft will still copy over the content on the first save, but the entry won’t be live for this locale yet, you first have to explicitly enable the locale in the right pane of the edit entry view.


Show entry on certain date, regardless of year

I fear this is not possible with a simple postDate parameter and you have to find a workaround.
The Twig apporach would be to loop all events and filter the right ones with a simple conditional.

{% set events = craft.entries.section('events').limit(null).order('postDate asc') %}
{% for event in events %}
    {% if event.postDate|date('m-d') == now|date('m-d') %}
        ...
    {% endif %}
{% endfor %}

If you'd like to paginate the results, collect / merge entry IDs within the for loop first and
then prepare another ElementCriteriaModel with these IDs in its id param, to get the entries.


You can use the instance of test (docs)

{% if field is instance of ('craft\\fields\\PlainText') %}

or use className (docs).

{% if field.className == 'craft\\fields\\PlainText' %}

In full:

{% for tab in entry.fieldLayout.tabs %}

{{ tab.name }}

    {% for field in tab.getFields() %}

            {% if field is instance of ('craft\\fields\\PlainText') %}
                {{ field.name }}
                <input type="text" name="fields[{{ field.handle }}]" value="{{ attribute(entry, field.handle)}}">
            {% endif %}

    {% endfor %}
{% endfor %}

You can see all native Craft field types here.


You could also export the data to a CSV with your own SQL commands. These commands could be created in a way to take parameter that your client could set through the CP.

You'd need to create a plugin with a controller method that runs your SQL query. Take a look at the docs for more info on querying the database.


Craft’s bootstrap file in located at craft/app/index.php. Importing that will get you 99% of the way there.

The only problem is, index.php not only loads Craft, it also runs it. In doing so, Craft is going to insist that it completely resolves the request, with a response to the browser.

I’m thinking we should move most of that code into a new bootstrap.php file, with the only exception being the last line:

$app->run();

Then index.php would simply import bootstrap.php and call $app->run() itself. That way you could import bootstrap.php rather than index.php, and do whatever you want with the app, like fetch entries, without losing control over the whole request.

In the meantime, you could copy the contents, sans $app->run(), of index.php into your own file and import that instead. You’d need to go through it and update all of the paths, too.

Another option would be to make Craft think the page should be a 404, and catch the 404 exception:

// Make it look like a 404
$_GET['p'] = "some/invalid/path";

// Import Craft, catching the 404
try
{
    require 'path/to/craft/app/index.php';
}
catch (\Craft\HttpException $e){}

// ...

Little hacky, but that may be your cleanest option until we give you a bootstrap.php file to import instead.

UPDATE

As of Craft 2.2, Craft now ships with a bootstrap.php file which handles all of the app initialization stuff with the exception of actually calling run().

When you include bootstrap.php(), a new Craft application will be returned.

$craft = require 'craft/app/bootstrap.php';


Get and display a product's variant fields in twig

It looks like I'm trying to use variants the way options can be used. I'm going to go with options.


Relational field validation (entries, assets, tags, users, etc.) works the same on the front-end as any other custom field would.

So if you have an Entries field with a handle houseCollege on an entry and it's marked as required and there is nothing submitted on the front-end for it, then using the error macro you mentioned:

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

            {% for error in errors %}

{{ error }}

            {% endfor %}

    {% endif %}
{% endmacro %}

You would display any validation errors for that houseCollege field with:

{% if entry is defined %}
    {{ errorList(entry.getErrors('houseCollege')) }}
{% endif %}

And in the case of a missing required field, you'd get:

House College cannot be blank.


Display number based on position in structure hierarchy

What about using CSS for your numbers? (Yes, this answer makes your question sound a bit off-topic, sorry for that, hehe)

Mainmenu:

.mainNav {
  counter-reset: mainNav;
}
.mainNav-item {
  counter-increment: mainNav;
}
.mainNav-item::before {
  content: counter(mainNav) ". ";
}

Submenu (double digits):

.subNav {
  counter-reset: subNav;
}
.subNav-item {
  counter-increment: subNav;
}
.subNav-item::before {
  content: counter(subNav, decimal-leading-zero) ". ";
  color: gold;
}

.

Edit:

Misunderstood that
 problem at first. I don't think that there's a dedicated function in Craft to get the position in a structure.

But you can get the entry position like so. You have to get all the structure entries that are on the same structure level with a new ElementCriteriaModel (→ new DB Queries) and then you do a conditional to find the position of the current entry.

{# Get the IDs of all the sections #}
{% set currentSectionId = entry.id %}
{% set allSectionIds = craft.entries.section('myStructure').level(1).ids() %}

{# Define var before loop #}
{% set sectionNumber = '' %}

{# Loop through all section IDs and find the one that matches the current #}
{% for key, sectionId in allSectionIds if sectionId == currentSectionId %}

    {# Use array key to calculate the section's position #}
    {% set sectionNumber = key + 1 %}

{% endfor %}

{# Save the section's position in a custom data attribute #}

Test

Use CSS to style your heading:

h1:before {
  content: attr(data-section-no) ". ";
}


Drawing the map is multiple API calls. And interacting with the map uses additional API calls.
I opened the Inspector (in Firefox here), and you can see a ton of calls to maps.google.com - see all the file calls vt?pb... - each one is a block of the map background.

And then, as you drag the map around, zoom, etc, it's making additional calls to get the portions of the map it doesn't have. And you can see them pop-up in the inspector.
So, a bunch of calls to draw the map, and more as you change your view of the map.
You could try the static image map {{ craft.smartMap.img(locations, options) }} instead of the standard {{ craft.smartMap.map(locations, options) }}
Alternative ideas, disable 'zoomable' and/or 'scrollable' in your map settings (more about those options here) - less interaction = less api calls.
The static map loads a lot less API resources, but takes a longer to generate (and just isn't as good).


How to fetch Category of current Entry and build "Next / Prev" urls

A category is an element. So is an entry, and an asset, and a tag, and user. When you relate one element with another you get returned an ElementCriteriaModel in the template. So you need to use its methods to actually get the element data. In this case first().

So if you know for sure that you only have (and care about) one category in an entry, then you can try this for your params.

{% set params = craft.entries.section('projects').order('title asc').relatedTo(entry.category.first()) %}

You could also set category way up at the top of the template if you know you'll
use it multiple times in the template. That way you are only making one database query.

{# At the top of the template #}
{% set category = entry.category.first() %}

{# Somewhat lower to display the category #}
{{ category.title }}

{# even lower to pull the other entries. #}
{% set params = craft.entries.section('projects').order('title asc').relatedTo(category) %}


Perhaps using redirects and Regex in your .htaccess? There's a Craft plugin that would help with this.
https://github.com/rkingon/Craft-Plugin--Redirect-Manager/

You could use something like:

RedirectMatch 301 /download/(.*) /several/subfolders/for/organisation/purposes/$1

You would need to refine this for matching several different subfolders.


How to build a transactional email platform with Craft

This answer will focus on using Sprout Email for transactional emails.

Transactional Emails

First, a comment on semantics. I feel the question above is drawing a distinction between two types of transactional emails: triggered and automated.

Triggered emails are a one-off, context-specific email that get sent to a user when an event is triggered by a user's interaction with the application. Automated emails, which seems to be the focus of the question, are transactional in the sense that they are a one-to-one email to a user, however the email is not triggered by a specific event, but by an automated process. A user takes an action to be placed in a specific category, and transactional emails are sent to all users in that category on a specified schedule.

Triggered emails are fairly easy to build a UI around in Craft. Automated emails are harder, as you probably have to rely on either tasks (which can't be reliably scheduled at a specific time) or cron-jobs (which require extra steps by web developers to be setup).

Sprout Email and triggered emails

While the default Sprout Email Notifications are mostly User and Entry events, Sprout Email is not at all limited to User and Entry events.

Sprout Email has a flexible Custom Event API where you can create custom triggers for the events you need to support with as many settings as you wish to control them with. An example can be seen in Sprout Forms, which adds a trigger for When a form entry is submitted.

Sprout Email allows you to manage the Triggered Email content right in Craft alongside your other content and all the admin needs to do is select the event which should trigger them being sent.

Sprout Email and automated emails

You'll have to create a custom script and setup a cron to ping your script to send out emails on the schedule you require, but Sprout Email can support (and is in use for) advanced transactional campaigns that allow content editors to easily manage email content in a Craft-friendly way, and programmatically send out transactional email on a regular schedule.

You can programmatically trigger a Notification Email using the Sprout Email service layer. Notification Emails are sent via the SproutEmail_DefaultMailerService using the sendNotification() method:

craft()->sproutEmail_defaultMailer->sendNotification($campaign, $object);

$campaign needs to be a SproutEmail_CampaignModel
$object is any object that you want to make available to your email templates.

At some point we'll probably add additional support in Sprout Email around dynamic list management and automated emails. Right now, it's quite possible, it just requires a custom integration that fits your needs.


Have the country in craft.commerce.countriesList default

Not particularly proud of this code, but if you want to do it from Twig, something like this:

{% set countryList = ['United Kingdom', 'United States'] %}

{% for country in craft.commerce.countriesList() %}
    {% if country != 'United Kingdom' and country != 'United States' %}
        {% set countryList = countryList|merge([country]) %}
    {% endif %}
{% endfor %}

    {% for country in countryList %}

{{ country }}

    {% endfor %}


Yes, you're right, one could call this a reverse-relation. The field you created the relation from is the "people" entry and you're looking at it from the category element's page.

To describe this direction in Craft relatedTo parameter, you define whether the element you're dealing with is the sourceElement of that relation, which means it is the element with the field, or if it is a targetElement, one of the elements selected in the field.

So on your "Our Skills" page you have a category element that got selected from a categories field, this makes it a targetElement. I'm also setting that categories field's handle here.

{% set individuals = craft.entries({
    section: 'people',
    relatedTo: {
        targetElement: category,
        field: 'mySkillsFieldHandle'
    }
}) %}

In most cases you could just use the element property, because there are no other relations between both elements. But I actually like to always define my relations precisely, because who knows what we add to the site in the future, that potentially breaks loose definitions.


How to query for multiple relations with SuperTable

It's a little hard to follow your example/description, but I'll take a stab at it.

The way I interpret your question, you need to pull a single guestList entry that is a) related to the current event, and b) shares a relationship with the partner entry set to the current user's partner field, via a guestAllocation SuperTable field owned by the event EntryModel (I'm assuming there's a guestAllocation.partner column, and that the event section has the event handle).

The first part is easy, although you seem to be confused about the targetElement and sourceElement parameters for the relatedTo method, so I'll try to clear that up:

Basically, in a relatedTo query you either specify the target element or the source element (never both) for the relationship – depending on which element owns the field where relation is created.

In your case, the event entry would be the target element, not the source, as the relatedEvent field (where the relation is created) belongs to the guestList entry model, not the event. In other words, the elements you want (the guest lists) should have the entry you have (the event entry) selected in a field (i.e. the guestLists entries "target" the event entry), not the other way around. If possible, you should also provide the field handle for the field where the relation is created, i.e. relatedEvent in your case. So, to pull all guestlists related to the current event entry, the correct relatedTo query would look like this:

{% set guestListsForEvent = craft.entries.section('guestList').relatedTo({
    targetElement: entry,
    field: 'relatedEvent'
}) %}

Obviously, you only want one guestlist – the one that is related to the current user's partner entry (phew!). Trouble is, that relationship doesn't really exist – it's actually more of a condition, where a) the guestList entry needs to be authored by a user with the correct partner relation, and b) the current event needs to have the correct partner entry (i.e. the current user's related partner entry) in its guestAllocations SuperTable field.

The second part is easy – you can set a canCurrentUserCreateGuestList flag inside a loop on the current event entry's guestAllocations field; if the correct partner event is found in the latter, the current user can create a new guestList entry and you should also query for an existing guestList entry:

{% set currentPartner = currentUser.partner.first %}
{% set currentUserCanCreateGuestList = false %}
{% for row in entry.guestAllocation %}
    {% if row.partner|length and row.partner.first.id == currentPartner.id %}
        {% set currentUserCanCreateGuestList = true %}
    {% endif %}
{% endfor %}

Once you have that flag, you can use it in a conditional:

{% if currentUserCanCreateGuestList %}
   {# Query for existing guest list, create new list etc #}
{% endif %}

For the latter – the actual query to pull the guestList entry – a single relatedTo call obviously won't do the job here, but fortunately the workaround is quite simple – keeping in mind that you need to make sure that a) only 1 guestList entry is returned, and b) that entry is authored by a user with the same partner entry as the current user.

Again, the first part is easy – simply use limit and first to pull a single entry (I like to add a |default(false) filter to suppress errors if no entries are returned).

For the second part, you'll first need a list of user IDs for all the users that are related to the current user's partner entry, and then feed that array to the authorId parameter for the craft.entries call:

{# Get the IDs for all users related to the correct partner #}
{% set partnerUserIds = craft.users.relatedTo({
    targetElement: currentUser.partner.first,
    field: 'partner'
}).ids() %}

{# Get existing partner guest list related to the current event #}
{% set partnerGuestList = partnerUserIds|length ? craft.entries.section('guestList').relatedTo({
    targetElement: entry,
    field: 'relatedEvent'
}).authorId(partnerUserIds).limit(1).first|default(false) : false %}

The above code will return either a single guestList EntryModel, or false, if no related guestlist entries authored by a user with the correct partner entry exists. Whether or not the event entry has the current user's partner entry in one of its SuperTable guestAllocation.partner columns is irrelevant to the query itself, once you've established that the current event does indeed include the correct partner entry in its guestAllocations field (the conditional above).

Here's how the whole thing could look in context:

{# Can the current user create a guest list for this event? #}
{% set currentPartner = currentUser.partner.first %}
{% set currentUserCanCreateGuestList = false %}
{% for row in entry.guestAllocation %}
    {% if row.partner|length and row.partner.first.id == currentPartner.id %}
        {% set currentUserCanCreateGuestList = true %}
    {% endif %}
{% endfor %}

{# Get existing guest list #}
{% set partnerGuestList = false %}
{% if currentUserCanCreateGuestList %}
    {# Get the IDs for all users related to the correct partner #}
    {% set partnerUserIds = craft.users.relatedTo({
        targetElement: currentUser.partner.first,
        field: 'partner'
    }).ids() %}

    {# Get existing partner guest list related to the current event #}
    {% set partnerGuestList = partnerUserIds|length ? craft.entries.section('guestList').relatedTo({
        targetElement: entry,
        field: 'relatedEvent'
    }).authorId(partnerUserIds).limit(1).first|default(false) : false %}
{% endif %}

{# Create, edit, etc #}
{% if partnerGuestList %}
    {# Edit existing guest list #}
{% elseif currentUserCanCreateGuestList %}
    {# Create new guest list #}
{% else %}
    {# Do nothing? #}
{% endif %}

Note that the above isn't tested and there's a good chance I misinterpreted your question – but hopefully you'll take something away from it.

Finally, as your question also touches on the correct usage of relatedTo queries with multiple relation criteria: Your original syntax for the relatedTo call is close, but when you have multiple relation criteria, you'll need to include either and or or as the first parameter, specifying if all or any of the criteria should be met, respectively.

In your case, this means the syntactically correct multiple relation query for the partner guestlist should look something like this:

{% set partnerGuestList = craft.entries.section('guestList').relatedTo('and',
    { target: entry, field: 'relatedEvent' },
    { targetElement: currentUser.partner.first(), field: 'guestAllocation.partner' }
) %}

Obviously, for reasons already explained the above query will return nothing. There's also the fact that SuperTable fields (in your case, the guestAllocation.partner field) doesn't actually work with the built-in relations functionality in Craft – meaning that you can never use craft.entries.relatedTo when the relation is created in a SuperTable field. Instead, SuperTable provides its own method for relation queries, which is explained in this answer. Again, I don't believe a single relatedTo call is the correct approach for your particular use case, but just wanted to mention it.

Just for funsies – here's how you could use SuperTable's getRelatedElements method to pull event entries based on guestAllocation.partner relations:

{% set partnerEvents = craft.supertable.getRelatedElements({
    relatedTo: {
        targetElement: currentUser.partner.first,
        field: 'guestAllocation.partner'
    },
    criteria: {
        section: 'event'
    }
}) %}


How can I rename an asset file on upload when an entry is saved (Craft 3)?

The code below is working for me so far. The answer at https://craftcms.stackexchange.com/a/28168/298 helped me figure things out for Craft 3.

Event::on(
    Entry::class,
    Entry::EVENT_AFTER_SAVE,
    function(ModelEvent $event) {
        /** @var Entry $entry */
        $entry = $event->sender;
        //Set entry's author ID
        $authorId = $entry->authorId;
        //Set value of custom field
        $imageOrder = $entry->myCustomField;

        if ($entry->enabled && $entry->section->handle === 'mySectionHandle' && $entry->type->handle === 'myEntryTypeHandle') {
            /** @var Asset $asset */
            foreach ($entry->myAssetField as $asset) {
                $newFileName = "0" . $imageOrder . "-" . $authorId . "-" . date('YmdHis') . "." . $asset->getExtension();
                Craft::$app->assets->moveAsset($asset, $asset->getFolder(), $newFileName);
            }
        }
    }
);

Can it be improved? For e.g., can I do without the foreach loop? Let me know and I'll update this answer and then mark it as accepted.


I've tried the way described here: https://github.com/craftcms/locales but that does not seem to be picked up by Craft 3.

Haven't actually tested this, but looking at the code I think it should work.

You'll need to disable the intl extension from being loaded on your box (usually done in php.ini) because if Craft sees that's available, it will use that automatically.

If it's not available, it falls back to config/locales, which is where you should be able to put your "custom" locale.


How do I get a list of craft provided events at runtime?

Events don’t get pre-registered anywhere in Craft, so there’s no way to easily fetch a definitive list of all events that will ever get called, but with a little PHP we can get a pretty good idea of what they all are.

You’d start by getting a list of all the components on WebApp (what craft() returns) by calling its getComponents() method, loop through each of them, use reflection to get each of their methods, and find the ones that start with on. (By convention, all event methods should start with that, and non-event methods generally shouldn’t start with that, although it’s possible this will yield some false positives, so make sure you double-check the results.)

$events = [];
$components = craft()->getComponents(false);

foreach ($components as $id => $component)
{
    // Skip some non-existent components
    if ($id == 'fieldTypes' || $id == 'file')
    {
        continue;
    }

    // If the component hasn't been loaded yet, $component will just be its config array
    if (is_array($component))
    {
        $component = craft()->getComponent($id);
    }

    // Find the event methods
    $class = new \ReflectionClass($component);
    $methods = $class->getMethods(\ReflectionMethod::IS_PUBLIC);

    foreach ($methods as $method)
    {
        if (strncasecmp($method->name, 'on', 2) === 0)
        {
            $events[] = $id.'.'.$method->name;
        }
    }
}

// Dump 'em out
Craft::dd($events);


For a field outside the Matrix, you can use {username} and for the one in the Matrix, use {owner.username} - see docs

You might need to run Utilities → Asset Indexes.


How to use the default HTML email template when sending an email from a plugin?

There are different ways

Extending the E-mail template in your template

This could be your email template emails/_someMail

{% extends 'path/of/your/layout-same-as-you-inserted-in-your-cp' %}

{% block main %}Hello World{% endblock %}

And in your PHP file

use craft\mail\Message;

$message = new Message();
$message->setTo('john@doe.com');
$message->setSubject("Hello world.");
$message->setHtmlBody(Craft::$app->getView()->renderTemplate('emails/_someMail'));
$message->send();

Render the correct template from the beginning

You can do exactly the same as Craft does in it's function - but I would suggest the first way

$systemMessage = Craft::$app->getSystemMessages()->getMessage('test_email', $message->language);
$subjectTemplate = $systemMessage->subject;
$textBodyTemplate = $systemMessage->body;

// Use the site template mode
$view = Craft::$app->getView();
$templateMode = $view->getTemplateMode();
$view->setTemplateMode($view::TEMPLATE_MODE_SITE);

// Use the message language
$language = Craft::$app->language;
if ($message->language !== null) {
    Craft::$app->language = $message->language;
}

$settings = Craft::$app->getSystemSettings()->getEmailSettings();
$variables = ($message->variables ?: []) + [
        'emailKey' => $message->key,
        'fromEmail' => $settings->fromEmail,
        'fromName' => $settings->fromName,
    ];

// Render the subject and textBody
$subject = $view->renderString($subjectTemplate, $variables);
$textBody = $view->renderString($textBodyTemplate, $variables);

// Is there a custom HTML template set?
if (Craft::$app->getEdition() === Craft::Pro && Craft::$app->getMailer()->template) {
    $template = Craft::$app->getMailer()->template;
} else {
    // Default to the _special/email.html template
    $view->setTemplateMode($view::TEMPLATE_MODE_CP);
    $template = '_special/email';
}

$e = null;
try {
    $htmlBody = $view->renderTemplate($template, array_merge($variables, [
        'body' => Template::raw(Markdown::process($textBody)),
    ]));
} catch (TemplateLoaderException $e) {
    // Clean up before throwing
}

// Set things back to normal
Craft::$app->language = $language;
$view->setTemplateMode($templateMode);

if ($e !== null) {
    throw $e;
}

$message
    ->setSubject($subject)
    ->setHtmlBody($htmlBody)
    ->setTextBody($textBody);


In a plugin, what's the way in PHP to output a CSRF token?

Maybe try craft()->request->getCsrfToken(), see if that does it?

Edit

Sorry, misunderstood the question, since you are saying your plugin has a CP section then i'm assuming you're actually looking for a twig way to output the CSRF input, not so much a PHP way. To output the CRSF input in your template simply do {{ getCsrfInput() }}


How to make a sortable table in frontend?

I can think of a couple ways to pull this off but Craft has many of the pieces already in place.

I'd create a new Channel, name it Organizations. You can add whatever fields you want in there (like address, city, etc.)
To leverage Craft's relations,  create a new field (Organization) that relates back to the Organization channel you just created and add it to the user's profile.

That's the information architecture bit. It'd be up to you how you want to collect the information. Maybe when a user registers for their account for the first time, you'd ask for details.

Then in a custom plugin, you'd probably want to validate to make sure the organization entry didn't already exist before creating a new entry in Organizations channel. Then set the relationship of that newly created entry to the User.

The great thing about Craft is the UI is up to you. So you might use any number of table sorting plugins.

Craft can even handle the Pagination for you. I think DataTables does ajax pagination out of the box, so your Twig template could just need to feed it the data.


"How does X work?" is a very broad question, and not one I intend to try and answer in detail here. Below are a few resources that should help get you started:
Robust queue job handling in Craft CMS
How to best design large queue jobs?
Also, here are all questions tagged with queue:
https://craftcms.stackexchange.com/questions/tagged/queue
Hope that helps!!


For most sites, there probably wouldn't be a difference, but if you're purely looking at performance and your site has a large number of assets, then 20 sources with 5,000 images and folders in each is going to scale better than a single source with 100,000 images and folders in them.


Store Hours: show current open/closed state

An answer to point 1)

{{ location.hours[now|date('w')].open < now and location.hours[now|date('w')].close > now ? 'Open now' : 'Closed' }}

And that same logic can be used to resolve issue 2)


How would you handle subscriptions and recurring payments using Craft Commerce?

At time of writing (22/08/16) - there is no support for subscriptions in Commerce.  You could attempt to do them as traditional products but I suspect it would be a lot of custom work.

It's a very frequently requested feature and I suspect proper subscriptions support will come to Commerce sooner rather than later.  Hopefully much sooner!

In the meantime, the solution most people seem to talk about is the Charge plugin instead of Commerce (or alongside Commerce for other commerce needs): https://squarebit.co.uk/software/craft/charge


To repopulate the form fields you can use the data from the post request using something like:

value="{{ craft.request.getPost( 'options.text' ) }}"

I also think I've got a rough solution for handling the errors.

//Add the cart to your event
$cart = craft()->commerce_cart->getCart();

//Check for field/fields
$text = craft()->request->getPost( 'options.text' );

//Check if it's got a value
if ( $text === '' )
{
  $event->performAction = false;

  //Build the handle we'll attach the error to
  //Use the purchasable id (variant) and then add the field we're checking for
  $lineItemErrorHandle = $item->purchasable->id . '-options[text]';

  //Add the error to the cart
  $cart->addError( $lineItemErrorHandle, 'The text is required' );
}

Then in your template you display it with the following where product.defaultVariant.id needs to be the id of the purchasable that attempted to be added to the cart.

{% set string = product.defaultVariant.id ~ '-options[text]' %}
{% if cart.getError( string ) %}
  We've got an error its {{ cart.getError( string ) }}
{% endif %}

I had to build the string outside of the .getError method because string interpolation wouldn't work using '#{product.defaultVariant.id}-options[text]'


How can I create a family tree hierarchy in Craft?

I can't think of an easy and clean way to visualize this kind of structure in a default list. So if you want to be able to display the structure from your diagram dynamically you'll have much work to calculate the positions correctly in a clear way.

So I would suggest you to use easy Craft methods. You could create an entries field to relate your children with all the upper level parents, in your case you would have

Parent 1 - no relation
Parent 2 - no relation
    Child - related to [Parent 1, Parent 2]
        Grand Child - related To [ Child ]
    Sub Parent 1 - related to [Parent 1, Parent 2]
    Sub Parent 2 - related to [Parent 1, Parent 2]
         Grand Child 1 - related To [Sub Parent 1, Sub Parent 2]
         Grand Child 2 - related To [Sub Parent 1, Sub Parent 2]
         Grand Child 3 - related To [Sub Parent 1, Sub Parent 2]

So you can get each parent of an entry with entry.fieldHandle.find()
and you can iterate through the tree. But this will only work well when don't mix trees.. So when you have a Parent 3 and 4 with another tree like in the diagram and one of those entries can be the parent of one of the grand children in the first tree you could have trouble (performance wise) to iterate to the beginning. You can collect all parents with no problem but if you have 5+ levels you'll need many queries and it could take a lot of time in Craft2 with default ElementCriteriaModels. But that's always the case in those NxN tree connections

I don't see any issues as long as your trees are separated from each other and as long as you use custom code to fetch the entries.


Next and Previous Entries that match condition?

You can add the "non-empty body" conditional to your parameters, as follows:

{% set params = craft.entries.section('portfolio').body(':notempty:') %}
{% set previousEntry = entry.getPrev(params) %}
{% set nextEntry = entry.getNext(params) %}
{# …and so forth #}


One structure section for multiple menu's (navigations)

This is something i've used, it should work for you, the only downside to it is there being a hardcoded id.

{% set nav = craft.entries.section('yourStructureSection') %}

{% set headerItems = nav.descendantOf(TopMenuId) %}

{% set footerItems = nav.descendantOf(BottomMenuId) %}

So you would just replace TopMenuId with the entry id of Topmenu and BottomMenuId with the entry id of Bottommenu

Then you will be able to loop through each nav :)

Edit

<nav>
 {% nav entry in craft.entries.section('contentPages').descendantOf(13) %}
    <li> <a href="{{ entry.url }}">{{ entry.title }} </a>
        {% ifchildren %}
            <ul> {% children %} </ul>
        {% endifchildren %}
    </li>
 {% endnav %}
</nav>


Define "best". It's one way of doing it but has a couple of issues. They need to log in to see this (I presume, otherwise one issue is that there are public facing things on the website no actual visitor cares about) but it's not in the dashboard. So there's a log in then navigate to the front end and get the page workflow which is less than ideal) Why not just put them in a global table field and let the client view/copy/edit them there?
Your merge needs square brackets. You're trying to merge an object not an array. Try

{% set theRows = craft.entries.section('theSection').one() %}
{% set siteVariables = [] %}
{% for row in theRows %}
  {% set siteVariables = siteVariables | merge([{ (row.name): row.value}]) %}
{% endfor %}


How to order by related entry type field

Try something slightly different in concept...

On your Products template - /products/index.html - start with your Authors first and then look for the Products which are related to them.

Hopefully this will help you make sense of it...

{# find all author entries #}
{% set authors = craft.entries.section('authors').order('title') %}

    {# loop through all author entries #}
    {% for author in authors %}

{{ author.title }}

        {# find any products which may be related to the author #}
        {% set products = craft.entries.section('products').relatedTo(author) %}

            {# Loop through related products by this author #}
            {% for relatedProduct in products %}

{{ relatedProduct.title }}

            {% endfor %}

    {% endfor %}

Also, if your Authors will ever need to log in to Craft, then consider adding them as CMS Users instead of entries. I know this has licence fee implications, but it's just a thought.

Craft's relatedTo parameter is the key concept to understand. More info here: https://craftcms.com/docs/relations


Retrieve entries on custom field date using ElementCriteriaModel

The Error was because

  $criteria->inspectionDate > '("now")';

This way you can't get today's date.

You could try this:

$date = new DateTime();
$formattedDate = $date->format(DateTime::MYSQL_DATETIME);
$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'inspections';
$criteria->inspectionDate = '> '.$formattedDate;
$criteria->order = 'dateCreated asc';
$inspections = $criteria->find();


Venti Events causing failed DeleteStaleTemplateCaches task

0.9.14 is still the beta version.  Go into the Venti_EventManageService file and delete the two lines with this string craft()->templateCache->deleteCachesByElement($element);.


AssetFileModel's getPath should do what you're looking for.

<img ix-path="{{ asset.getPath() }}" alt="Test Image">


I think that, right now, the only way to deal with that is at the DB level. I believe you would only have to deal with the craft_relations table for adding / removing categories to entries.


Auto-generated title based on last entry

Something like this should do what you're looking for:

{% if not object.id %}{{ craft.entries.section('scripts').order('postDate DESC').first().title + 1 }}{% else %}{{ object.title }}{% endif %}


Use Same Email Address On Multiple User Accounts

Not natively because Craft places a unique index on the email column of the craft_users table in the database.

Without knowing the specifics of what you're trying to achieve, I'd probably write a custom plugin that listened to user registration events in Craft and saved the necessary LDAP information in its own database tables that had foreign keys back to the native craft_users table.


Craft Commerce: No Emails sent on Default Order Status

I just tested this with a default Craft Commerce installation, assigned an email to the default "Processing" order status, placed an order and received the email as expected.

I'd double check under Settings->Email in the Craft control panel you're not using phpmail or sendmail and you're using a proper SMTP server or transactional email provider like Mailgun or Mandrill, etc.  The others are notoriously unreliable at delivering email.  See: https://craftcms.com/support/troubleshooting-email-errors#dealing-with-email-delivery-issues


YouTube video embeds in rich text field not saving

My guess is you're running into one of two issues.

You're bumping into your php.ini file's max_intput_vars and/or post_max_size limitations.
Your server has something like Suhosin or mod_security installed and the content you're trying to save in the Rich Text field is triggering one of their security rules.


Is there a way to generate a url to an image in the craft/storage/myplugin directory?

Since craft/storage/ is not publicly accessible, your only real option here is to serve them through Craft as Resource Requests. (This is the vehicle through which Craft serves up all of the CP’s front end resources, which live in craft/app/resources/.)

The actual resource URLs will depend on the site’s resourceTrigger config setting, so to generate the URLs you should use URLHelper::getResourceUrl():

$url = UrlHelper::getResourceUrl('myplugin/some/path.jpg');

Your templates can call the corresponding resourceUrl() function as well:

{{ resourceUrl('myplugin/some/path') }}

Then you will need to add a getResourcePath hook method to your primary plugin class, which would detect incoming resource requests and resolve them to the actual server path in craft/storage/.

public function getResourcePath($path)
{
    // Does this path start with "myplugin/"?
    if (strncmp($path, 'myplugin/', 9) == 0)
    {
        // Return the path to the file in craft/storage/
        return craft()->path->getStoragePath().'myplugin/'.substr($path, 9);
    }
}

It’s worth mentioning that you’re always going to get worse performance out of serving files through PHP than you would if they were located somewhere that’s publicly accessible. So you might just want to have the user create a new folder somewhere under their web root, and have them specify the path/URL to that folder, just like local asset sources.


Question can be deleted, just found my mistake...

Apparently I've forgot to create the 'fr' folder and the index.php etc..

Working like a charm now!

Post, can be deleted as it won't be helping others


“Request missing required body param” error when creating entry on front end

This was an unintentional breaking change. See https://github.com/craftcms/cms/issues/4693

Update: Fixed in 3.2.9, which is now (2019-08-06) available https://github.com/craftcms/cms/blob/develop/CHANGELOG-v3.md#329---2019-08-06


Show Entries based on content in a Matrix Field

I was finally able to piece this together using Brad's explanation of MatrixBlocks parameters and this thread Can I get an entry by Matrix Block ID?

Seems merge([block.owner.id]) was the piece I was missing to fold the MatrixBlock query back into an entries loop.

{# Find Matrix Blocks with field value #}
{% set blocks = craft.matrixBlocks.type('variant').fieldId(33).salePrice(':notempty:').all() %}

{# Get entry IDs #}
{% set saleEntryIds = [] %}
{% for block in blocks %}
    {% set saleEntryIds = saleEntryIds|merge([block.owner.id]) %}
{% endfor %}

{# Get entries with limit #}
{% set saleProducts = craft.entries.section('shop').id(saleEntryIds).limit(4) %}

{% for product in saleProducts.all() %}
    {{ product.title }}
    {% for block in product.productVariants.all() %}
        {{ block.salePrice }}
    {% endfor %}
{% endfor %}

Seems a little overly complicated - maybe there's an easier way to do it?


Is there a way to get supportedSites for a category page?

It turns out that getSupportedSites() returns different results for categories and standard entries so an additional check needs to take place.

The solution below has been tested with a single group with multiple languages, and it works, although I hope there's a better solution than this one:

If the current page is a category then assign it to the entry variable

{% set entry = category %}

Then:

{# Retrieve all supported sites for the current entry #}
{% set supportedSites = entry.getSupportedSites %}

{% for siteForEntry in supportedSites %}
  {% if siteForEntry | length == 1 %}
    {# category #}
    {% set site = craft.app.getSites.getSiteById(siteForEntry) %}
    {% set entryForOtherSite = craft.categories.id(entry.id).site(site).one() %}
  {% elseif siteForEntry | length == 2 %}
    {# standard entry #}
    {% set site = craft.app.getSites.getSiteById(siteForEntry.siteId) %}
    {% set entryForOtherSite = craft.entries.id(entry.id).site(site).one() %}
  {% endif %}

  {% if site.id == entry.siteId %}
      {# This is the current language, mark it as active and don't retrieve its url #}

{{site.language}}

  {% else %}
      {# if it's not the current site, get the entry for this site #}

{{site.language}}</a

  {% endif %}

{% endfor %}


Templates starting with an underscore character is by default denied direct access in Craft (resulting in a 404 not found error). I guess that renaming your template to "results" should fix it.


Cannot access assets - unable to open image

The solution to my problem was installing the ImageMagick package.

Regarding the S3 bucket - Craft 2 doesn't support my region (Frankfurt) - read more here.


Is it possible to image upload on a particular size using a control panel?

Yes, you can use image transform option for that.
You should go to control panel and go to below path
Settings > Assets > Image Transforms
Then create new image transform.
Using it, you can control height, width, image quality, image format and other things as well.


Is it possible to separate variant options on a front end add to cart form?

It's definitely possible and doesn't really need any custom back end code to be done in general.

Ultimately all add to cart options in Commerce are just a simple case of POSTing the variant id and the quantity of that variant.

Generally I would do this all in twig & a bit of JS.

E.g. In twig I wouldt loop through all variants (checking for stock as I go) and build up a JSON array of all the combinations of colour & size, and their availability due to stock.  I'd then 'pass this into' my form as a data-variants attribute.

Actually building the selects is slightly trickier because one will depend on the other but basically you'd probably want some JS that listens to your selects and looks at your passed in array to see if a particular size and colour combination was in stock - if a chosen combination is not, some sort of visual indication and disable the add to cart button, otherwise if it is in stock the form just posts the variant id and the qty and away you go.

Updated with some sample  code:

Here's some untested/pseudo code that should get you on the right track:

so the important thing to understand is that the descriptive data of a variant is really a completely separate concern to the sku of the variant - which in turn is not actually all that relevant to commerce - the variant id is really all that matters in the end in terms of addToCart.  For specifiying the variant data you can do it any way you like really but in this case if it's just say 3 colours and 3 sizes, then a simple approach would be a dropdown for each of those, with handles colour and size say.

You then just make the 9 variants, choose the colour and size for each, and enter the sku for each.

Then, you want to make the JSON for use in the JS.  (It's hard for me to see how you'd have a good UX without JS here, to be honest).

Here the |jsonencode filter is handy.  Something along the lines of:

{% set stockArray = [] %}
{% for variant in product.variants %}
    {% set stockArray = stockArray|merge([{variantId:variant.id,
                                          variantColourAndSize :variant.colour ~ "-" ~ variant.size,
                                          variantIsUnlimited:variant.unlimitedStock,
                                          variantStock:variant.stock,
                                          }]) %}
{% endfor %}

Then you output your form and pass this consolidated data in to it so it's accessible in the JS:

<form id="OrderForm"
    data-stockarray="{{ stockArray|json_encode() }}"
    data-action="/actions/multiAdd/multiAdd"
    data-redirect="/cart"
    etc

>
<selects here>

The rest is really just JS operating on that json data - this is thoroughly pseudo code since it's Friday night :) - but should be enough to get the idea:

var $form = document.getElementById('OrderForm');
var stockArray = $form.dataset.stockarray;
// Listen to your selects and look up in this array whether the matching colour/size variant is in stock/has unlimited stock
var variantKey = $select1.val() + "-" + $select2.val();
if(stockArray[variantKey].variantIsUnlimited || stockArray[variantKey].variantStock > 0 ){
// Enable/Disable your add to cart button accordingly
    $addToCartButton.show();
}
else {
    $addToCartButton.hide();
}


You've probably gone through the process of creating a new Section, but have not assigned any fields to it.

In Craft, the differences between each of your Sections and Entry Types comes in the various fields you assign to them.

I suggest you take a look at the intro to Sections and Entries, then at Fields.

The typical content structure definition process looks something like:

Create a Section and at least one Entry Type
Create a Field Group
Add Fields to the Field Group
Add the Field Group or individual Fields to your Entry Type(s)
Add or Edit your content by creating or modifying an Entry.

In your case, you've probably done step 1 and step 5. Try adding some fields (like "Body" or "Tags") and assigning them to your Entry Type.


Calling onSaveEntry event only for one section

You would compare against the entry's section / entry type in a conditional. The entry modal is available from the event params $event->params['entry'].

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

    if($entry->section['handle'] == 'mySection' && $entry->type['handle'] == 'myEntryType')
    {
        // Execute for mySection / myEntryType entries only!
    }
}


Setting Google maps circles using Smart Map plugin

This is a shot in the dark, so let me know if this does/doesn't work...

Here's how you're starting your loop:

$.each( smartMap.marker, function( key, value ) {

And near the end, you reference a marker object:

circle.bindTo('center', marker, value.getPosition());

But as far as I can tell, marker is never defined. Did you mean to pass in value instead?


For Craft 2, these are the values you're looking for...

window.csrfTokenName = "{{ craft.config.get('csrfTokenName') }}";
window.csrfTokenValue = "{{ craft.request.getCsrfToken }}";

They changed slightly in Craft 3, which can be seen here...


List products related to currently active category (url)

The same way as entry is available if you hit an entry, the variable category is available if you hit a category.

Thus the following code:

{% if category is defined %}
    {# Specific category selected #}
{% else %}
    {# No specific category selected #}
{% endif %}