Server's IP in URLs in cached templates I'm running Craft CMS 3.3.11 on an EC2 machine with Apache and Load Balancer.

After upgrading to Craft 3, I'm having issues with caching.

I use relative paths to resources/assets in my templates (i.e. href="/resources/logo.svg"

After some time, the relative paths in the template are not handled properly - instead of domain name in the URLs I get the server's IP address. It's impossible to fetch data using IP address, so the website is loading forever, the assets won't show up and it logs an error to the dev console:

  Mixed Content: The page at ‘https://example.com/’ was loaded over HTTPS, but requested an insecure image ‘http://172.xx.xx.xx/cpresources/8f9c0f5e/logo.svg?v=1572966078’. This content should also be served over HTTPS.

When I clear caches, everything works properly again.

Adding {{ siteUrl }} before all the relative paths seems to be the easiest fix, but I wonder if maybe I have some configuration issues that should be fixed to prevent this in future?

Server's IP isn't stored neither in the database nor the template files - where does it come from?

Suggestions?

EDIT

Unfortunately it still doesn't work properly.

Here's my code:

                {% endif %}

                {% if craft.rebrand.isIconUploaded() %}

                {% endif %}

For these assets Craft is using server's IP... Can someone please advise?

These are probably coming from the incoming request in the $_SERVER PHP superglobal

Yii2 does its best to figure out the incoming request, but that's relying on information coming from the client, which is insecure. Note the warning about potential cache poisoning in the Craft CMS docs:

  Don’t ever use the @web alias when defining your sites’ Base URLs. It could introduce a cache poisoning vulnerability, and Craft won’t be able to reliably determine which site is being requested.

This is for the same reason; if no explicit siteUrl is provided, it'll try to figure it out from the request.

In your case, craft.rebrand.getLogo().url ends up calling getImageVariable which then ends up calling the Yii2 asset manager to get the published URL. I think your siteUrl or other aliases may not be set properly.

    /**
     * Returns the schema and host part of the current request URL.
     *
     * The returned URL does not have an ending slash.
     *
     * By default this value is based on the user request information. This method will
     * return the value of `$_SERVER['HTTP_HOST']` if it is available or `$_SERVER['SERVER_NAME']` if not.
     * You may want to check out the [PHP documentation](https://secure.php.net/manual/en/reserved.variables.server.php)
     * for more information on these variables.
     *
     * You may explicitly specify it by setting the [[setHostInfo()|hostInfo]] property.
     *
     * > Warning: Dependent on the server configuration this information may not be
     * > reliable and [may be faked by the user sending the HTTP request](https://www.acunetix.com/vulnerabilities/web/host-header-attack).
     * > If the webserver is configured to serve the same site independent of the value of
     * > the `Host` header, this value is not reliable. In such situations you should either
     * > fix your webserver configuration or explicitly set the value by setting the [[setHostInfo()|hostInfo]] property.
     * > If you don't have access to the server configuration, you can setup [[\yii\filters\HostControl]] filter at
     * > application level in order to protect against such kind of attack.
     *
     * @property string|null schema and hostname part (with port number if needed) of the request URL
     * (e.g. `http://www.yiiframework.com`), null if can't be obtained from `$_SERVER` and wasn't set.
     * See [[getHostInfo()]] for security related notes on this property.
     * @return string|null schema and hostname part (with port number if needed) of the request URL
     * (e.g. `http://www.yiiframework.com`), null if can't be obtained from `$_SERVER` and wasn't set.
     * @see setHostInfo()
     */
    public function getHostInfo()
    {
        if ($this->_hostInfo === null) {
            $secure = $this->getIsSecureConnection();
            $http = $secure ? 'https' : 'http';

            if ($this->headers->has('X-Forwarded-Host')) {
                $this->_hostInfo = $http . '://' . trim(explode(',', $this->headers->get('X-Forwarded-Host'))[0]);
            } elseif ($this->headers->has('Host')) {
                $this->_hostInfo = $http . '://' . $this->headers->get('Host');
            } elseif (isset($_SERVER['SERVER_NAME'])) {
                $this->_hostInfo = $http . '://' . $_SERVER['SERVER_NAME'];
                $port = $secure ? $this->getSecurePort() : $this->getPort();
                if (($port !== 80 && !$secure) || ($port !== 443 && $secure)) {
                    $this->_hostInfo .= ':' . $port;
                }
            }
        }

        return $this->_hostInfo;
    }


Eager loading category data from a Matrix block How might I eager load category data in a plugin? I can't seem to figure out why I can't access a category in this way:

locationOffers is a matrix block name, category is the handle of a related category field inside of the matrix block

// this adds an empty category array to each related offer
$relatedOffers = $entry->locationOffers->with(['category'])->all();
print_R($relatedOffers->category); // is empty

// this regular way works, where I can access category->title, and more,
// but is not eager loaded
$relatedOffers = $entry->locationOffers->all();

Apologies, I misread the question the first time around.

When eager loading via a matrix block, you need to provide a blocktype as well as the field name.

See: https://docs.craftcms.com/v3/dev/eager-loading-elements.html#eager-loading-elements-related-to-matrix-blocks for more details


Update from 3.5.19 to 3.6.15 Failed Tried doing an update to 3.6.x from 3.5.19 from the terminal and got this horrifying message:
``
Performing one update:
- craft 3.5.19 => 3.6.15

Backup the database? (yes|no) [yes]:yes
Backing up the database ... done
Performing update with Composer ... Killed
``
php version is 7.4.3
The Composer,json file was changed to require Craft 3.6.15, but looks like no other files were actually changed, there is nothing in the logs and, thankfully, the website is working fine.I have done similar updates on other sites without a problem. Any suggestions for how to troubleshoot this? "Killed" is not much of a starting point.
Thanks!

The Composer "Killed" error messages usually means Composer ran out of memory.
https://github.com/composer/composer/issues/1815
Either your on a VM with limited resources or your php.ini file has a low memory_limit set.
Increasing the memory, in either case, should resolve it.


How to use `{% cache %}` and `{% paginate %}` together? When using cache tag with pagination should the tag go outside the pagination tag?

{% cache %}

    {% paginate craft.entries.section('employment').endDate('>= ' ~ now).limit(10) as pageInfo, pageEntries %}
    {% for entry in pageEntries %}

{{ entry.title }}

                        {% if entry.openUntilFilled %}
                            Open Until Filled
                        {% else %}
                            Job Closing: {{ entry.endDate.format('M j, Y') }}
                        {% endif %}

{{ entry.body|length > 1 ? entry.body|striptags|slice(0, 150) ~ '...' : entry.body }}

Read More

    {% endfor %}

        {% if pageInfo.prevUrl %}Previous Page&nbsp;{% endif %}
        {% if pageInfo.nextUrl %}Next Page{% endif %}

{% endcache %}

Yes, the database query you'd want to cache is this:

{% paginate craft.entries.section('employment').endDate('>= ' ~ now).limit(10) as pageInfo, pageEntries %}

So to get the benefits of caching, it needs to be within the cache tag.


How to return asset from custom user field In Craft 3, one of my 'User' fields is an assets type field with one selectable asset ('profilePicture').

I have routing setup to load my template when a url looks like:

domain.com/person/firstname-lastname

In my template I am getting the appropriate user with:

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

{% set people = craft.users.group('family') %}

{% for person in people %}
    {% set personName = person.firstName|lower ~ "-" ~ person.lastName|lower %}
    {% if secondSegment == personName %}
        {% set currentUser = person %}
    {% endif %}
{% endfor %}

All that works - I can query most fields, but I can't work out how to get my asset.

Works:

{{ currentUser.myTextField }}

None of these work (returns nothing and no error):

1.

{{ currentUser.profilePicture[0].url }}

2.

{% set asset = currentUser.profilePicture.first() %}

{% if asset %}
    {{ asset.getUrl }}
{% endif %}

3.

{% for asset in currentUser.profilePicture %}
    {{ asset.getUrl }}
{% endfor %}

You have to make sure you enabled the option Assets in this volume have public urls in your volume settings at /admin/settings/assets/volumes/.

This checkbox is disabled by default thus your getUrl() function will always return an empty string/null.


Importing Entries from ExpressionEngine This is essentially my first project with Craft and my plan is to take a personal photoblog and move it into Craft to learn how everything works before working with clients and craft.

I've got craft installed locally at testing.craft.dev and want to import my existing ExpressionEngine entries.

I've renamed the default "news section" to photography, added a new image upload asset and field to the layout. All of which I can see when Igo to Entries > Photography.

Now to import the entries I found Craft Import. I've installed this, created an xml file on my EE install.

<xml>
<blog>
{exp:channel:entries channel="photoblog" show_future_entries="yes" limit="500"}
<entry>
    <entry_date>{entry_date}</entry_date>
    <title>{title}</title>
    <slug>{url_title}</slug>
    <post><![CDATA[{description}]]></post>
    <images>
    {photos}
        {image}
    {/photos}
    </images>
</entry>
{/exp:channel:entries}
</blog>
</xml>

I've also set the url to this xml file on line 17 of services/craftservice.php. Where I'm stuck is that I now need to Update Lines 64-73 to match your Craft configuration and source nodes. Reference inline comments. Those lines are:

    // Find these in craft/app/models/EntryModel
    $entry->sectionId = $sectionId;
    $entry->typeId = $typeId;
    $entry->authorId = 1; // 1 for Admin
    $entry->enabled = true;
    $entry->postDate = $importEntry->entry_date;
    $entry->slug = $importEntry->slug;
    $entry->getContent()->setAttributes(array(
        'title' => $importEntry->title,
        'post' => $post
    ));

Unfortunately I have no idea what I need to put in here. Any advice would be greatly appreciated.

As it stands if I try to load entry I get an error, no surprise there.

  CDbCommand failed to execute the SQL statement: SQLSTATE[42S02]: Base
  table or view not found: 1146 Table 'crafttest.craft_entries_i18n'
  doesn't exist

As per Brandon's request in the comments to the original question here are the steps I used to import. Below is copied from a blog post I wrote with screenshots.

NOt sure why but my code bits are not displaying even though I've used the code button in the wysiwyg here. To see the full code bits go to my blog.

First use a different plugin https://github.com/boboldehampsink/import

copy all files from original site
in the Craft CP click the gear icon on the top right, then Assets, New source and fill in the fields. both the path and url can be set to relative paths, but be sure to not use a leading slash.
After saving click the gear icon again and go to the lower left and update asset indexes.
The next step is to install the Import plugin by putting the files in /craft/plugins then in the CP click gear and plugins and finally install.
This plugin only imports content in CSV format. This requires a new template in ExpressionEngine which will need to be set wiht php turned on in order to force the browser to download the file directly.

The next bit of code contains all our fields and how we want them named. This is important to easily map the fields using the import plugin. Line 20 has entry_date with extra spaces this is due to my blog rendering it and not displaying the code correctly - remove extra spaces for it to work. When migrating images, be sure to only include the image name. My images currently reside in a Matrix field {photos} and a file cell. In order to get just the file name it is necessary to use the file tag pair like this {image}{file_name}{/image} where the outer tag pair is the file field/cell name.

   Title
    Url Title
    Entry Date
    Description
    Image

{exp:channel:entries channel='photoblog' limit='500' disable="categories|member_data|pagination|comments" status="not foo"}

            Migrating Content from ExpressionEngine to Craft
            {url_title}
            { entry_date }
            {description}
            {photos}{image}{file_name}{/image}{/photos}

{/exp:channel:entries}

After downloading the file open it in Excel, you may see a warning that the file format doesn't match the extension, open it anyhow. Now do a save as and choose CSV (comma delimited). My research indicated that this extra step is necessary as using the template to save as CSV with content that contains quotes may not work correctly.
Now to import, click Import in the Nav. Fill in the fields as required and upload your CSV file.
Go to the next page where we map the fields to Craft fields.


Craft 3 devMode doesn't turn off I've been working on a site locally in devMode. I moved it from Craft 2 to Craft 3. I set devMode to false in config/general.php file and in admin it doesn't show the devMode bar at the top, but everything in the front of the site was pointing to my local environment.

The only thing that has worked is setting my siteUrl in the 'dev' to the actual site

// Dev environment settings
'dev' => [
    // Base site URL
    'siteUrl' => 'https://footwearoutfitters.net',

    // Dev Mode (see https://craftcms.com/support/dev-mode)
    'devMode' => false,
]

While this works, I'm concerned if it thinks it's running in devMode I'll have potential security threats.

I missed this in the .env file, I'll leave this here in case anyone else is as bad a space case as myself. :)

# The environment Craft is currently running in ('dev', 'staging', 'production', etc.)
ENVIRONMENT="dev"


Why when a task is marked as “Stalled” the following tasks can't automatically processed? This is annoying to have to click on “Try again” to unlock the queued tasks. This could leads to dozen and dozen of stucked tasks that usually could be processed without any problem (like the Generating search keywords tasks).

I know there are recommandations about how to avoid stuck stacks, and we have setup a lot of these. But from time to time, we still face tasks marked as “Stalled” (and sometimes not) on several websites.

I know cron jobs using runTasksAutomatically setting or taskrunner plugin could also avoid this by calling the runPendingTasks at a more regular interval than connect to the Control Panel from time to time.

There's probably a good answer for that, but why when there's a task marked as “Stalled” in the Control Panel, this one is not ignored to automatically let the following tasks processing? And is there a way to automatically ignored these tasks marked as “Stalled”?

why when there's a task marked as “Stalled” in the Control Panel, this one is not ignored to automatically let the following tasks processing?

Because tasks behind it might rely on the data that the successful completion of the stalled task would generate.

  And is there a way to automatically ignored these tasks marked as “Stalled”?

You could probably hack it somehow, but I wouldn't recommend it.  It's best to fix the underlying reason the task stalled in the first place.


How can I return the number of users registered after a specified date? Ok little stuck on this. I am trying to return the number of users registered after a specific date. So far I have tried the below using after but it is still returning all users regardless of the date.

craft.users.status('active,pending').after('2015-06-22').total()

Any help appreciated.

Something like this should do it:

craft.users.status('active,pending').dateCreated('> 2015-06-22').total()


What are the advantages/disadvantages of the various cloud storage solutions for assets? When setting up a new assets source, Craft allows you to natively connect to one of these cloud storage solutions (assuming you're using the Craft Pro edition):

Amazon S3
Google Cloud Storage
Rackspace Cloud Files

I know that the answer may be subjective, but want to hear pros & cons from people who have tried any of these. I'm working on a project which will require one of these solutions, and I greatly value the opinions of this community.

Allright, I'll bite. First, I'll get the cost argument out of the way, then I'll cover each type with their specifics.

Costs

Amazon S3: USD 0.03 per GB (up to 1TB, where the price drops as you store more and more data)
Rackspace: USD 0.12 per GB (up to 1TB, where the price drops)
Google Cloud Storage: USD 0.026 per GB (No price reduction for large amounts)

In conclusion - pricing will not be a deciding factor, as the difference, while having a rather noticeable amplitutde, only matter when storing such an absurd amount of data, that the price is the least of your problems.

S3 Specifics

Superb integration with AWS. If you're hosting there, then your choice has been made.
CDN - Amazon Cloud Front is super-easy to set up and is a breeze to use.
Different types of storages available.

Regular
Reduced Redundancy Storage - cheaper, however Amazon guarantees "only" 99.99% durability of data
Glacier - super-cheap storage for archiving. Super long data recovery, though. I'm talking 3 to 5 hours. Also, as Matt Stein pointed out, in some cases, the data retrieval could get super-expensive. (more info, expensive retrieval case)

Supports object versioning (more info)
Cache headers - you can set up cache duration per Assets source for files uploaded to the source via Assets

Rackspace Specifics

CDN built right in - no set-up necessary.
CDN comes at a cost - you can purge only up to 25 files from the CDN per day, so be careful with frequent file changes. (blog post)
Supports object versioning (blog post)

Google Cloud Storage Specifics

Cheapest of them all.
Offers Durable Reduced Availability storage. Cheaper, but stores data on further servers, so the data recovery time is slightly longer.
Cache headers - you can set up cache duration per Assets source for files uploaded to the source via Assets
According to google, CDN is built in at no extra cost. (Google groups post))
Supports object versioning (more info)

Overview

I am biased, I'll admit that, but I've had nothing but joy working with Amazon S3, a lot of frustration working with Rackspace and mixed feelings when it comes to Google. For Google it's mainly of their unbelievably clunky UI, but that might be just me.


craft.matrixBlocks element queries with .type() I'm using Craft Pro 3.0.0-beta.19 and I try to query matrix blocks with craft.matrixBlocks(). Background: I have event series (=structure) with a matrix block containing 1:n dates for each series. My block type in the "dates" matrix block is "eventDate" and looks like this:

this works:

{% set entries = craft.matrixBlocks() %}

Since this is the first matrix block I have I get all the entries I have (2):

{{ entries | length }} will output: 2
{{ entries.one().type }} will output: eventDate

Good.

Now I want to limit the blocks to eventDate only

{% set entries = craft.matrixBlocks.type('eventDate') %}

On the first glance this seems to work, I get the same results.

But when I change this to

{% set entries = craft.matrixBlocks.type('WhateverGoesHere') %}

I still get the same results. Am i not understanding this or is it a bug?

Thanks,
Matthias

This was a bug in a beta version of Craft 3 (fixed here: https://github.com/craftcms/cms/commit/9b6dad7385c5a82d1c83d230fe6ce0cfe940675b)


Return previous or next enabled sibling of same parent I want to link to enabled sibling entries within a structure and am struggling to get it working.

This is what my structure looks like:

Because I only want to fetch entries that are enabled, I followed the docs instructions and fetch previous entries like this:

{% set prevEntry = craft.entries.positionedBefore(entry).order('lft desc').first() %}

With this, when on the Prince Phillip entry, I thought that would return null for prevEntry, but it is returning the Altynia Asylmoratova entry.

How can I fetch previous and next entries that are direct siblings and enabled?

After trying a few more things, I realised I needed the descendantOf parameter to get this working.

This is what my code looks like:

{% set prevEntry = craft.entries.descendantOf(entry.parent).positionedBefore(entry).order('lft desc').first() %}
{% if prevEntry is null %}
  {% set prevEntry = entry.siblings.last() %}
{% endif %}

{% set nextEntry = craft.entries.descendantOf(entry.parent).positionedAfter(entry).first() %}
{% if nextEntry is null %}
  {% set nextEntry = entry.siblings.first() %}
{% endif %}

This restricts the positionedBefore and positionedAfter parameters to only work with entries that have the same parent as the current entry.

If there is no previous or next entry, I link to the first or last sibling entry instead, creating a loop.


.find() not working with live preview? I have an Entry Type with a field called Gallery with a handle of gallery. Here are two examples of how I can access the Gallery field in a template:

{% set images = entry.gallery %}

{% set images = craft.assets({
    source:    'images',
    relatedTo: {sourceElement: entry.id, field: 'gallery'},
    order:     'sortOrder'
}) %}

The problem:

The first method works with Live Preview, the second does not. This wouldn't be an issue, but it's my understanding that we have to use the second method to eager load elements. So if I wanted to eager load a relationship on my gallery images, then Live Preview wouldn't work.

Is anyone else running into this issue? Is it a known bug or a misunderstanding of the implementation?

Thanks

Edit

To clarify via Brad's question, the following is the only thing in my template. This does NOT work with Live Preview:

{% set images = craft.assets({
    relatedTo: {sourceElement: entry.id, field: 'gallery'}
}) %}
{% for image in images %}
    {{ image.url }}

{% endfor %}

The entry variable is populated defining the Entry Template in the section settings.

Using the following WORKS with live preview:

{% set images = entry.gallery %}
{% for image in images %}
    {{ image.url }}

{% endfor %}

As noted in the comments above, eager-loading is not yet compatible with Live Preview. A clean workaround is to disable eager-loading in the template when the page is being viewed in Live Preview:

{% if craft.request.isLivePreview %}
    {% set images = entry.gallery %}
{% else %}
    {% set images = craft.assets({
        relatedTo: {sourceElement: entry.id, field: 'gallery'}
    }) %}
{% endif %}

{% for image in images %}
    {{ image.url }}<br />
{% endfor %}


Cart Items Total to include qty of variants By using line total: {{ cart.lineItems|length }} it returns the number of 'products' in the current sessions cart. However, this doesn't seem to take into account the qty of each variant.

So if I add 3 of variant A and 2 of variant B, the lineItems|length would equal 2. But I want to cart to show there are 5 items added.

How can I get the total of all the items in the cart including qty of each variant?

You can get the total quantity of items with:

cart.totalQty

Docs: https://craftcommerce.com/docs/order-model#totalqty


What's the difference between "is defined" and "is not null"? {% if var is defined %}

and

{% if var is not null %}

Is there a difference in usage of them?

is defined - The variable has been defined, and set to any value (or null).

is not null - The variable has been defined, and is specifically not null.

In PHP terms, it's like the difference between is_null() vs. checking whether the variable exists using get_defined_vars() (see this Stack Overflow thread for a little more clarity)

Try this experiment... Without setting myVar, put this in your template:

{{ (myVar is defined) }}

Since that equates to false, nothing will appear in your template. Now change it to this:

{{ (myVar is not null) }}

That will actually throw an error, since myVar was never defined.


Feed Me plugin not mapping Neo fields I have Neo fields in my entries which I want to be populated by a JSON feed pulled in through Feed Me, im using elementApi top create the JSON feed.

The Feed Me setup runs fine and there are no errors. My issue is that I'm un-able to map the Neo Fields when it comes to the configuration screen (where you select the Feed Element from your fields to map with the JSON fields), because I am only seeing the top-level of the Neo fields.

Any help would be greatly appreciated

Just by the way, Neo is currently not supported with Feed Me. You're welcome to upvote this feature request - https://github.com/verbb/feed-me/issues/335


Update Asset Index in Batches I have 80,000+ files on S3 that need to be added to Craft. The Update Asset Indexes works, but takes over 24 hours and cannot be interrupted. Does anybody have a way to programmatically index assets like this in batches?

Your best bet for a quick hacky solution would be to interrupt the indexing process, take a look at craft_assetindexdata table and then write a small plugin that calls craft()->assetindexing->processIndexForSource().

You would get the sessionId from the craft_assetindexdata table and you'd be able to deduce how far the indexing has gotten by looking at the same table. All the entries that have recordId field set to a value have been processed already.

This way you can batch it up however you want.


Checking if a plugin is installed or enabled are ignored by Twig Extensions A while ago I asked how to check if a plugin is enabled/installed. I've since used a couple methods to do my checks:

{% set plugin = craft.plugins.getPlugin('myPlugin', false) %}

{{ plugin.isEnabled() ? 'plugin enabled' : 'plugin disabled'}}

{{ plugin.isInstalled() ? 'plugin installed' : 'plugin not installed'}}

{{ craft.myPlugin is defined ? 'plugin true' : 'plugin false' }}

Now I recall this working with Twig Extension functions and filters too. It wasn't pretty, but it worked.

I may wrong, but I think one of the Craft CMS Updates have broken this. Because as-of-late, when I do something like this:

{{ craft.myPlugin is defined ? myFunction() }}

or

{{ craft.myPlugin is defined ? someVariable|myFilter() }}

(myFunction being a twig function, and myFilter being a twig filter)... I get an error:

  Unknown "myFunction" function

Another new change/bug I've noticed (related to this); if a database can't be connected to and devMode is off, I will get this instead of the 503 error template.

  Unknown "myFunction" function in "_layouts/main" at line 85.

It's as if the Twig functions/filters get priority over anything else. Am I making this up, and this has always been the case? Or has something changed?

I just a test of this locally in a sample plugin and I get expected behavior.

If I install and enable the plugin in Craft and use this in a template:

{% set plugin = craft.plugins.getPlugin('myPlugin', false) %}

{{ plugin.isEnabled() ? 'plugin enabled' : 'plugin disabled'}}

{{ plugin.isInstalled() ? 'plugin installed' : 'plugin not installed'}}

{{ craft.myPlugin is defined ? 'plugin true' : 'plugin false' }}

I get this output:

plugin enabled
plugin installed
plugin true

If I add a Twig Extension class to the plugin, then register a myPluginTestFunction function that outputs "It Works"... i.e.

public function getFunctions()
{
    return array(
        'myPluginTestFunction' => new Twig_Filter_Method($this, 'myPluginTestFunction', array('is_safe' => array('html'))),
    );
}

public function myPluginTestFunction()
{
    return 'It Works';
}

Then I do this is a template:

{{ craft.myPlugin is defined ? myPluginTestFunction() }}

Then I get the expected output of:

It Works


How can I build a language switcher? I'm currently building a site with two languages, and I need a language switcher so wherever you enter the website you can switch the language easily.

I've come this far:

{% for locale in craft.i18n.getSiteLocales() %}
    <li {{ locale == craft.i18n.getCurrentLocale() ? 'class="active"' }}>
        <a href="/{{ locale }}/{{ entry.slug }}">
           {% if loop.first %}DE{% else %}FR{% endif %}
        </a>
    </li>
{% endfor %}

The problem here is that {{ entry.slug }} only returns the slug for the current language and doesn't loop trough the languages.

When I'm on french it returns /bonjour twice and on german it returns /hallo twice. Why is that?

I am building my first multi-language site with Craft as well. This is from a thread over at Google+, so I didn't come up with this myself but it works very well:

{% block locale__switch %}

    {# Loop through all of the site locales, except the current one #}
    {% set otherLocales = craft.i18n.getSiteLocaleIds()|without(craft.locale) %}
    {% for locale in otherLocales %}

        {# Find the current entry in the other locale #}
        {% set localeEntry = craft.entries.id(entry.id).locale(locale).first %}

        {# Make sure that it's actually localized to this locale #}
        {% if localeEntry.locale == locale %}

            {# Output a link to it #}
            {{ locale }}
        {% else %}

            {# Output a link to the hompage #}
            {{ locale }}
        {% endif %}

    {% endfor %}
{% endblock %}

I set this up in a block to implement the switch in various templates. It loops through all the languages minus the current one and outputs the links. It also matches the entries by ID which is why you can have different slugs. Hope it helps.

Yay for the craftcms.stackexchange site!


Sending email by key to non-user In a custom plugin, I would like to use Craft's ability to register email message keys in order to keep emails consistent, and I would like to be able to send these emails to users as well as non-users. My understanding is that I would need to use the sendEmailByKey method of the EmailService to send emails using registered keys, which is defined like this:

public function sendEmailByKey(UserModel $user, $key, $variables = array())

This method only accepts a UserModel for the recipient, so it doesn't look like there's a way to send an email by key to an arbitrary email address. Is there a different way to send these registered emails to non-users?

Just because EmailService::sendEmailByKey() requires you to pass in a UserModel, doesn’t mean that the model has to represent an actual saved user. You can create one on the spot for them:

$user = new UserModel();
$user->email = 'sergster@abc.xyz';
$user->firstName = 'John'; // optional
$user->lastName = 'Doe'; // optional

craft()->email->sendEmailByKey($user, 'my_key', $variables);


Dynamic URI to load entry template This may be asking the impossible, but I'm trying to do the following:
Say I have 3 channels, Country, Region, and Town. Town has an entry field to select a Region, a Region entry has a field to select a Country.
I want the URL for a Town entry to look like https://website.something/uk/west/torquay, or https://website.something/portugal/south/faro. Both of these URLs would load the template specified for the town. A URL of https://website.something/france/south would load a Region template.
I'm guessing I'll have to do some advanced routing?

Completely possible without any extra routing!
First you would need to make sure the relation fields are required to prevent any errors.
For the Country section, you would simply set up your section with the URI format { slug }
For Region you would set up the URI Format to grab the related Country's slug for the first segment, like this: { yourCountryFieldHandle.one().slug }/{ slug }
And for Town it would be { yourRegionFieldHandle.one().yourCountryFieldHandle.one().slug }/{ yourRegionFieldHandle.one().slug }/{ slug } which gets the related Region's Country for the first segment, then the related Region for the second.
You can then specify a different template for each section.


Nesting blocks - is the following problematic? I lazily added the following to my parent site template:

{% block body %}
    {% block content %}
    {% endblock %}
{% endblock %}

Is this 'allowed' in Twig ?

Yes, see the block tags docs. http://twig.sensiolabs.org/doc/tags/extends.html#block-nesting-and-scope


How do I get all categories with at least one entry I want all categories that have at least one entry that uses it.

You could do it like this:

{% set categories = craft.categories.relatedTo({
    sourceElement: craft.entries.limit(null)
}) %}

reference: https://craftcms.slack.com/archives/help/p1429030702000608


Displaying related image assets from another section with twig I have a site that shows upcoming football matches in a table, and I would like to include the clubs' logos next to each club name.

I have the following sections and entry types, both generated using an API and feedme to create entries

Teams section (includes fields for teamIDs and logos)
Matches section (includes fields for home team & home team ID, away team & away team ID, match time and location, but does not include logos)

The team ids and home/away team IDs match.

To display logos, I imagine the process should go something like this:

for each hometeam and awayteam in each row of the match table, identify the team ID
Use the ID to find the related teams in the teams section,
output the asset (logo) related teams logo in the match table.

This feels like a relatedTo / reverse relations problem, where i can say - in twig - something like:

{% if homeTeamId or awayTeamId in the fixtures section is the same as a Teamid field in the Team Section, then output that related teams's logo. %}

Can anyone suggest the most efficient way to structure this in Twig?

The best way is to change home team ID and away team ID to entry fields that select the club. If you are using a plugin like Feed Me to bring in the matches, and you have all of the club IDs already entered in the club entries, you should be able to import matches and use the home and away IDs and match them to the appropriate Club in Feed Me.

Once that is done, you won't have to loop through all of the Clubs, just pull the one from each of the matches home and away fields like so:

{% for team in fixture.homeTeamId.limit(1).all() %}
    {% for logo in team.clubLogo.limit(1).all() %}
        <img src="{{ logo.getUrl() }}" />
    {% endfor %}
{% endfor %}

If your API isn't brought in with Feed Me (or akin) and you can't change the home/away fields to entry selectable fields, you can select a team by matching its ID field to the given ID field like so:

{% set awayId = fixture.awayTeamId %}
{% set awayTeam = craft.entries.section('clubs').search('clubId:'~awayId).limit(1) %}
  {% for team in awayTeam %}
    ...


Add locales to section causes error Just Playing around with Craft and get this kind of error:

If I create a new locale and go to add it to a previously made section I get

  Internal Server Error -> Undefined offset: 0

I noticed that if I create a section after adding the locale I can then edit/remove/re-add locales without errors

(I'm on osx MAMP PRO - php 5.3.28 a module)

This is a bug that's been fixed in the next (post 2.3.2635) release of Craft.


Are categories the best way to organize Commerce product filters? The Commerce site I'm working on (my first Craft project) will have a product listing page with filters. These will function as you would expect, but clicking a filter name will link to another version of the product listing page with another set of products, as opposed to updating the page via AJAX. I'm doing the content modeling now and am wondering if Craft categories are the best way to structure this or if there is a better way. I see it working somewhat like the Patagonia product page (click through the categories toward the top of the sidebar and note the URI change). However, unless there's an advantage to doing otherwise, I was just going to use categories for both of the filter sets below. Patagonia uses query string parameters when filtering by sport, whereas this site would have a unique slug(s) for each combination of filters.

Here's what the filters look like. A checkbox or some other visual indication would be given when a filter is selected:

Product Categories

Category 1 (slug: category-1)
Category 2
Category 3
New Products

Shop by Use

Use A (slug: use-a)
Use B
Use C
Use D

The selection options are:

Only one Product Category can be selected at a time (choosing another deselects the previous selection), but a selection is not required.
Only one Use can be checked at a time (choosing another deselects the previous selection), but a selection is not required.
A selected filter can be unselected by clicking it.
With the Product Category and Use options unselected, a page with ALL products is displayed.

A few more notes:

Every product will belong to at least one Product Category but can belong to multiple.
Every product has at least one Use and most have multiple.
'New Products' is a unique category that would ideally expire based on a date chosen when adding a product.
I was picturing the URIs being something like the following:

Category selected: domain.com/products/category-1
Use selected: domain.com/products/use-a
Category and Use selected: domain.com/products/category-1/use-a or domain.com/products/category-1-use-a

Questions

Are categories the best tool for this job? If not, what would work better? If so:
Would it make sense for Product Categories and Shop by Use to be their own category groups?
Creating category pages is simple enough, but I'm not sure how best to create a page that represents a combination of categories / selected filters (e.g. Category 2 + Use A). I know I can use relatedTo to list products from multiple categories, but what is the best Craft element to use as a container for these pages? This answer was helpful, but it's not quite the same (for one thing, it's not Commerce-specific; it refers to products but I believe they are just standard channel entries). Should the combined-category pages be in their own channel?
New Products: I'm thinking this should be a static link, possibly to a single (/products/new) that lists products whose "newness" has not expired. Is there a better way?

I'm probably overthinking this! I mainly want to know if I'm heading in the right direction.

Hard to say if they're the 'best' tool, but I don't see anything here you can't do with Craft categories and they seem the logical and built in way to go about it.  In essence you simply look at your url segments and use these as category filters when retrieving the products
I think so.  It keeps the two separate data concerns nicely separated - but do be aware from a UI point of view, separate category groups are very separate things - you can't use one field to select from both groups (quite a surprise to me the first time I implemented this!)
I think you really only need one template here that simply inspects the url segments and builds the products query from whatever is there.  This part of the question reads a little as if you're confusing the presentation concerns and the data holding concerns (which is not criticism - it's very easy to do!) - your products will live as products over in Commerce, but your actual url routing and display of those at the category level (i.e. the product listing level) - can probably be handled by just one display template.  .  You don't need a 'channel' for these pages as such (they're not pages, rather filtered views).  So probably just a route that points, say, /catalogue/* -> to your one product listing template.  (The actual individual product pages (if they have significantly different displays) - can use multiple templates if need be (or again, conditional logic within the one template)).
There's really no reason that you could not use a route to point say  /products/new to the same template and again inspect the url to build your products query, showing only the newer products.  There's no need per se for a single here unless you want other content on the page or something.

While you described this on slack as a 'noob' question it's not, and it's good to think it through - in some ways this stuff is the hardest part to get your head around with Craft/Commerce.  Once you actually get to implementing it you'll find this bit was actually a lot harder than making it work (well, I did!).

The fact you're using separate urls for everything probably makes it a lot easier than some approaches I think, so nothing in your message really strikes me as unachievable.  The point to understand is that you don't need a channel or section to hold all of these pages - they aren't really pages as such, really they are all views on the same data (all, or some subsets thereof) - you simply have route(s) which point to a single template with logic that inspects the url and filters the products based on that.

More than happy to chat this through more on Slack if that would help.


Passing Multiple Relation Criteria In Plugin I have a channel (projects) that has two different entries fields (year & research theme), both of which I want to be able to search in a plugin.

The docs for the relatedTo entries method show under the heading "Passing Multiple Relation Criteria" that it's possible to do this within twig, however I'm not sure how to do this in my plugin using php. Obviously the below won't work:

# Find all projects that match the supplied year and research theme.
$projectCriterea = craft()->elements->getCriteria(ElementType::Entry);
$projectCriterea->section = 'projects';

# Something like this?
$projectCriterea->customField1->relatedTo = $yearEntryModel;
$projectCriterea->customField2->relatedTo = $researchThemeEntryModel;

$projects = $projectCriterea->find();

Any help would be amazing. Thanks.

I need someone more experienced with Craft to vet this, but it seems that this is working:

Supplying an array to relatedTo returns results if it matches one OR the other entry.

$projectCriterea = craft()->elements->getCriteria(ElementType::Entry);
$projectCriterea->section = 'projects';
$projectCriterea->relatedTo = [$themeEntry, $yearCat];
$projectResults = $projectCriterea->find();

If you supply "and" as the first entry in the array, it only returns results that are related to BOTH entries.

$projectCriterea = craft()->elements->getCriteria(ElementType::Entry);
$projectCriterea->section = 'projects';
$projectCriterea->relatedTo = ["and", $themeEntry, $yearCat];
$projectResults = $projectCriterea->find();

This was figured out by tinkering and guessing, hence I'm not sure it's the "correct" way to do this. It also doesn't let me search individual custom entries type fields, but this does do what I was after.


Add a Leading Zero with a number field I have a number field used for episode numbers and I would like to automatically add a leading zero when the number is less than 10. I have this working with a conditional but it seems inefficient. Is there a twig filter that I don't know about that does this?

{% if entry.episodeNumber < "10" %}
    {% set episodeNumber = '0' ~ entry.episodeNumber %}
{% else %}
    {% set episodeNumber = entry.episodeNumber %}
{% endif %}

The above works but seems overly long to accomplish what should be a simple task.

There aren't any filters built in to Craft (or Twig) that does this, but your {% if %} conditional could be trimmed down to a single-line ternary operation:

{% set episodeNumber = (entry.episodeNumber < 10 ? '0') ~ entry.episodeNumber %}

or even

<span>{{ (entry.episodeNumber < 10 ? '0') ~ entry.episodeNumber }}</span>


Widget initialized in Business Logic plugin not loading Hokay, this is a big one. Thanks in advance for anyone that has a look:

I’m trying to get this widget working on a Craft site.

The install documentation is pretty simple, I've hosted it here: http://brycekirk.com/documentation/

I've also installed Business Logic. Within that plugin, I've created a folder called vendor and and moved the psmw folder into it.

I've then initialized it in BusinessLogicPlugin.php:

public function init() {
    require_once 'vendor/psmw/init.php';
}

and added into /variables/BusinessLogicVariable.php, I've added the path to the shortcode functions, and a test one:

public function shortcode($optional = null)
{
    require_once(CRAFT_PLUGINS_PATH.'businesslogic/vendor/psmw/shortcode.php');
    shortcode(['type' => 'spark', 'symbol' => 'AAPL', 'template' => 'line', 'color' => 'blue']);
}

And then called it in my template with {{ craft.businessLogic.shortcode }}. It's generating HTML and JS, but not displaying the ticker, and I'm getting a jQuery is not defined error.

I'm sure there's something wrong with the logic behind how I'm loading in the plugin and its assets, I just can't figure out what it is. Any gesture in the right direction would be much appreciated! I can provide more info if needed.

Sounds like you haven't loaded jQuery on that page. You'll need to make sure that jQuery is loaded before your {{ craft.businessLogic.shortcode }} tag.


Combine image assets widths to get total width How can I check if multiple asset image widths combined are wider than X?
So how do i get X?

Like this:

File 1 = 300px wide
File 2 = 200px wide
File 3 = 250px wide

x >= 750px than

  Do This

else

  Do that

Something like this should work:

{% set totalWidth = 0 %}

{% for asset in myAssetList %}
    {% set totalWidth = totalWidth + asset.width %}
{% endfor %}

{% if totalWidth > 750 %}
    Do this.
{% else %}
    Do that.
{% endif %}


Why is the Algolia index population process with Search Plus timing out? I'm at a loss here. Hopefully, someone here can shed some light into a Search Plus plugin and Algolia index population issue I'm having.

I'm able to add an item (page, blog post, product) to the item's respective index by editing the item but when I kick off the Search Plus index population process it quickly times out/fails. I have an index that literally has one item.  It populates the index when I edit it but the same item does not get added to the index when done via the Search Plus index population process. I'm skeptical that this is an Algolia API record size limit because I just described but I could be wrong.

I do see the following errors in the Craft admin console:

2019-03-21 22:38:52
Level   error
Category    application
Message Encountered an error running task 2591 (SearchPlus_Population), step 1 of 2: Trying to get property of non-object on line 519 of /craft/plugins/searchplus/services/SearchPlus_AlgoliaService.php

2019-03-21 22:38:52
Level   error
Category    php
Message Trying to get property of non-object (//craft/plugins/searchplus/services/SearchPlus_AlgoliaService.php:519)

I'm running Craft CMS 2.7.6 and Search Plus 1.5.2 on Nginx with PHP-FPM 7.1.  I checked the the Algolia credentials are correct. I have adjusted the Nginx configuration and PHP's timeout settings and max post size settings.

I reached out to the Search Plus developer and he replied once telling to adjust the PHP configuration and has been unresponsive since the initial exchange.

Hopefully, someone here can shed some light on this issue.

Thanks.
Sal

Trying to get property of non-object on line 519 of /craft/plugins/searchplus/services/SearchPlus_AlgoliaService.php

That sounds suspiciously like a bug in the plugin to me.  I'd recommend contacting the plugin's author and reporting it to them for further debugging:

https://transition.topshelfcraft.com/software/craft/searchplus/faq/how-can-i-get-support


How to show to profile related data inside Users page in admin dasboard, also showing some addtional filters I would like to add some additional functionality in Users page, like adding profile related data which we are creating separately suppose, mother tongue, address, hobbies , and job related in same page of the User, can we somehow override the main users page in back-end admin dashboard to show these details as well along with main user data.
Also the admin should be able to create/modify or delete it.
Can you help me in this issue, I'm not able to redesign the page.

I might be misunderstanding your question, but you can choose which columns are shown on all of Craft's element index pages using the little cog at the bottom of the sub-nav sidebar. You can also add additional headings to the sidebar and rearrange them from here.
For non-superadmins, you need to grant permission for them to access this functionality by enabling the Customize element sources permission under Settings > Users > [User Group] > General.


Why aren't dynamic folders being generated for assets? I have a field 'Event Listing Image' set up as:

Field Type: Asset
Restrict uploads to single folder
Upload location [Events]{slug}

There's an asset bucket Events:

Local Folder
File System Path: {fileSystemPath}/content/events/
URL: /content/events/

The field is in a section named Events of type Channel.

The system folder /content/events/ exists and is writable.

If I edit an existing Entry in that channel, I can click upload in that field, but it errors every time with:

  Upload failed for test.jpg. The error message was: ”Error uploading the file: The folder “/Users/matt/Sites/bs_conwyarts/_bespoke/public/content/events/test-event/” does not exist.“

I know it doesn't, it's dynamic based on the entry slug. Why is Craft not creating the folder?

Irony: I have a field called Featured Image set up almost identically on a different Channel that does work:

Featured Image:

Field Type: Asset
Restrict uploads to single folder
Upload location [Artists]{slug}

Asset bucket Artists:

Local folder
File System Path: {fileSystemPath}/content/artists/
URL: /content/artists

UPDATE: looks like a bug. It works fine for new entries posted in the Events channel, it does not work for the existing entry in the Channel. I think I added the field in question after creating the first entry, so it looks like that might be the culprit.

Problem solved thanks to Craft Twitter support; needed to re-build the Asset Indexes; because I'd added that field after already creating an entry the asset index was stale and needed flushing.

Open Craft admin dashboard
Click Settings
Click Update Asset Indexes
Click Go!

This process scans through the list of assets in the database and ensures it matches what is in the file system and updates the database as needed.


Uploaded photos not showing on entry Please refer to this thread for information leading up to this problem.

I am having problems with mass file uploads, the files will upload in my CP for craft, and be present on the assets list, however when I come to post the entry, only one image will show on my live page.

Here is my code:

{% extends "_layout/_layout" %}

{% set bodyClass = "photos" %}

{% block metaTitle %}{{ entry.title }} Photo Gallery{% endblock %}
{% block metaDescription %}{{ entry.metaDescription }}{% endblock %}

    {% block content %}

{{ entry.title }}

        {{ entry.body }}

            {% set photos = entry.photos %}
            {% if photos | length %}
            {% for photo in photos %}

                                {% set image = photo.uploadPhoto.first() %}

            {% endfor %}
            {% endif %}

        {% set prev = entry.getPrev({'section' : entry.section.handle}) %}
        {% set next = entry.getNext({'section' : entry.section.handle}) %}
        {% if prev %}&laquo; {{ prev }}{% endif %}
        {% if next %}{{ next }} &raquo;{% endif %}

        Photographer credits.

    {% endblock %}

Any help with rectifying this code would be absolutely wholeheartedly appreciated!

Thank you!

It looks like you're trying to access another asset within your assets (asset meta field).

{% set photos = entry.photos %}

{# Loop assets of `entry.photos` as `photo` #}
{% for photo in photos %}

    {# Get first `uploadPhoto` element within `entry.photos[nth]` #}
    {% set image = photo.uploadPhoto.first() %}
    {{ image.getUrl() }}

{% endfor %}

I guess that's not what you want. Check your field handles again, you probably only need to do this.

{% set photos = entry.photos %}

{% for photo in photos %}
    {{ photo.getUrl() }}
{% endfor %}

If 'uploadPhoto' is an asset source and you allow users to upload to multiple sources, but only want to loop assets from 'uploadPhoto' in your template, you would do this like so.

{% set photos = entry.photos.source('uploadPhoto') %}


Using setTemplateMode on the frontend I'm trying to access a CP template from the frontend, and i'm doing something like this in my plugin:

<?php

...
$oldMode  = craft()->templates->getTemplateMode();
craft()->templates->setTemplateMode(TemplateMode::CP);

$widget = craft()->templates->render('plugin/Plugin_Template', array(
    'chatraID' => $chatraID,
));

craft()->templates->setTemplateMode($oldMode);
...

I'm getting the Unable to find the template error, though. I have verified that the plugin is installed, and that the template  plugin/Plugin_Template is accessible from the CP.

May have answered on Stack/plugindev:

@sjelfull  was intrigued, so started reading code about this, until the thought occurred: you seem to be asking a front end instance to access a CP template? This shouldn't be allowed unless it was a CP or action request, no?  The setting to TemplateMode can't fail this way, must be in trying to use the template, and that may fall apart at line 904 of TemplateService.php, would think. I don't put it past you to have another clever idea, though :wink: -- Takk for de...


Undefined index error in trying to duplicate file I've inherited a Craft-based website, and I'm much more familiar with WordPress, so please pardon the extremely basic question: the homepage for this site uses {% extends "_layout" %} and then references some field data associated with an entry (within "Singles") for "Homepage". I wanted to create a duplicate page to experiment with the template syntax, so I literally copied the contents of index.html into another file of the same name in a folder labeled "preview". Now, if I visit the site via www.site.org/preview I get the following error:

Internal Server Error
Undefined index: entry

I have tried numerous ways of identifying the source of the entries, e.g. set entries but I can't seem to get the field data to output. Of course, if I remove any reference to entry data, the rest of the template renders fine. Why on earth would simply duplicating the homepage file result in the above undefined error? I've tried re-indexing the site assets, clearing caches, etc. Thanks for any assistance here- I'm at my wits' end.

It's because of #2 here: https://docs.craftcms.com/v3/routing.html#dynamic-routes

index.html matches a route (likely you've got a Single section defined in Settings setup to load the index.html template).  Because of that, Craft will prepopulate the entry variable for that route in the template.

There currently isn't a route that matches preview/index.html, so Craft doesn't prepopulate the entry variable and you get the error you're seeing.


GraphQL: get prev / next entry from current entry (channel) Is there a way to get the prev and next entry from the current entry, when this entry is inside a channel and not a structure?
query ($id: [QueryArgument], $rel: Int) {
  entry: entry(id: $id) {
    id
    slug
    title
    uri
  }
  next: entry(nextSiblingOf: $rel) {
    id
    slug
    title
    uri
  }
  previous: entry(prevSiblingOf: $rel) {
    id
    slug
    title
    uri
  }
}

Output when the entry is in a structure:
{
  "data": {
    "entry": {
      "id": "145",
      "slug": "neuigkeiten",
      "title": "Neuigkeiten",
      "uri": "neuigkeiten"
    },
    "next": {
      "id": "150",
      "slug": "leistungen",
      "title": "Leistungen",
      "uri": "leistungen"
    },
    "previous": {
      "id": "141",
      "slug": "unsere-praxis",
      "title": "Unsere Praxis",
      "uri": "unsere-praxis"
    }
  }
}

and the result when the entry is inside a channel:
{
  "data": {
    "entry": {
      "id": "182",
      "slug": "david-hellmann-1-2",
      "title": "David Hellmann",
      "uri": "team/david-hellmann-1-2"
    },
    "next": null,
    "previous": null
  }
}

is there a way to get this data?

You should be able to use next and prev (see documentation and this issue).
query getEntryData($id: [QueryArgument]) {
  entry(id: $id) {
    id,
    slug,
    title,
    uri,
    prev(section: "blog", orderBy: "postDate desc") {
      id,
        slug,
        title,
        uri
    },
    next(section: "blog", orderBy: "postDate desc") {
      id,
        slug,
        title,
        uri
    }
  }
}


Customer info missing from email Folks:

The client receives an email with order details that include the customer shipping address. On a couple of occasions, though, the shipping details do not show. Notes:

The email is delivered without an issue.
The customer shipping address is missing.
The customer email still makes it through. Not sure why just the
email comes through but could be a fluke.
The order form does not allow the user to complete the transaction
without a shipping address.
Neither the commerce nor the craft log files show anything amiss.
Viewing the confirmation email source reveals nothing.

The customer confirmed that they entered all their details. The customer also confirmed that they are using standard Chrome and that they checked all their details before placing the order. They also attempted the same transaction a second time at the request of the client and they could not get past the address screen without entering a shipping address.

Any assistance would be appreciated.

Are you setting the requireShippingAddressAtCheckout and requireShippingMethodSelectionAtCheckout config variables to true?

https://craftcommerce.com/docs/configuration#requireshippingaddressatcheckout


Is it possible to reassign an existing event from one Solspace Calendar to another ? Let's say I have an existing event called "My Event" on a Solspace calendar called "Social".

Is it possible to reassign "My Event" to a different calendar eg: "Sports" - without deleting "My Event" from "Social" & recreating it on "Sport" ?

This currently isn't built into Calendar, but if your calendars use the same fields, you should be able to manually adjust the calendarID column in the craft_calendar_events database table. Otherwise, you'll have to delete the event and create it again for the correct calendar.

Sometime in the future we plan on seeing if we can add the option to allow changing of calendars. The issue for us is that each calendar is able to have a different field layout and tabs, etc, so it complicates things. :)


Retrieve entries by random sort, then resort alphabetically I need to pull X entries with

{% set randEntries = craft.entries.section('presenters').order('RAND()').limit(10) %}

But then sort them alphabetically on entry.lastName.

Do I need to Supersort for this, and if so, how do I apply it? Do I need to pull the entries first, and then run the sort?

I recon Supersort is they way to go, as its got some really handy functions to make this sort of thing a breeze. Try with the following:

{% set entries = craft.entries.section('presenters').order('RAND()').limit(10) %}
{% set sortedEntries = entries | supersort('sortAs', '{lastName}') %}

{% for item in sortedEntries %}
    {{ item.title }}
{% endfor %}


SEOMatic: Get SEO Image from a Matrix Field I'm using a matrix for hero images on my pages, and I'd like to use them as the SEO image in SEOMatic, but it's not available in the settings.

I tried setting the field to "Custom URL" and adding twig code:

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

If I place this in my template, it displays the path to the first matrix image, but SEOMatic seems to ignore it.

Is there another way to configure things to use my matrix images?

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

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

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

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

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


Is it possible to prevent disabled Matrix Blocks showing in a Live Preview? I have a template which loops through Matrix Blocks. The site itself correctly ignores any Blocks which are 'disabled', but on viewing the page in the Live Preview, those Blocks are visible. A key part of the reason for using Craft as the CMS for this site was the draw of the Live Preview, so this is important for us to get right.

I can't see anything as part of a Matrix Block Model which would indicate an assigned status to each Block which I could access. If there was, as there is with a straight entry, I could at least do some sort of a work around e.g. forcing the collation of Blocks to only those with a particular status of 'enabled'.

This feels like it might just be a bug; I am seeing other complications with this particular Live Preview, for instance if any offset or limit is given to the Blocks, rearranging the blocks in the Live Preview has no effect either.

If anyone could shed some light / offer some advice that would be much appreciated!

It's definitely a bug in live preview but looks like you can work around it.

This doesn't appear documented at all—so be careful—but you can use .status() to get the block's status. It looks like an IF block is enough to get a matrix block to refresh the live preview.

{%for block in entry.matrixBlock %}
   {% if ( block.type == 'supertable' and block.status == 'enabled') %}
  {#do whatever #}
   {%endif %}
{%endfor %}

I found out about .status out awhile back messing around trying to figure out if there was a good way to display a "sold out" status for a particular show date (for example):

{%for thedate in entry.showDates.type('date').status() %}

    {% if thedate.status() == 'disabled' %}
        {{thedate.showDate|date('m/d/y')}} SOLD OUT!
    {% else %}
        {{thedate.showDate|date('m/d/y')}}
    {%endif%}

{%endfor%}


How do you create a custom Twig tag? Say I'm building a plugin that adds user memberships to the website. I want to check on my front end templates that user's membership is active and I have built the functionality inside the plugin to do this.
How do I use a tag like {% requireMembership %} in place of the normal {% requireLogin %} to call the function that I've built? I thought it would be simple but can't find documentation on this anywhere.

There are two classes behind each Twig tag: a Token Parser and a Node.

The Token Parser is responsible for actually parsing the template, once Twig has tokenized it, and returning your Node class to represent it. The Node class is responsible for compiling itself into actual PHP code.

{% requireLogin %} is about as simple as it gets, because it doesn’t have to worry about parsing parameters, expressions, sub-content, etc. You can use its Token Parser and Node classes as a starting point - they’re located in craft/app/etc/templating/twigextensions/.

Once you’ve created those classes, you will need to create a Twig Extension, which will be used to connect your TokenParser to Craft’s instance of Twig. Give it a getTokenParsers() method which returns an instance of your Token Parser class (example).

(Note that if you use the Craft namespace in these clasess, you will need to prefix all of Twig’s class names with \, e.g. \Twig_TokenParser.)

Finally you need to register your Twig Extension from your plugin’s primary class using the addTwigExtension hook:

public function addTwigExtension()
{
    // Import the Twig Extension, Token Parser, and Node classes
    Craft::import('plugins.mypluginfolder.MyTwigExtension');
    Craft::import('plugins.mypluginfolder.MyTokenParser');
    Craft::import('plugins.mypluginfolder.MyNode');

    // Return a new instance of it
    return new MyTwigExtension();
}


How to save Asset field of an Entry programmatically in Craft 3 Using this answer on how to save data on Craft 3, I want to save also an asset field, but I cannot find out how.

It works for a Category field using the ids of the categories but not with ids of Assets.

Here is the code:

use craft\elements\Entry;
use craft\elements\MatrixBlock;

// Figure out the section & entry type
$section = Craft::$app->sections->getSectionByHandle('news');
$entryTypes = $section->getEntryTypes();
$entryType = reset($entryTypes);

// Create an entry
$entry = new Entry([
    'sectionId' => $section->id,
    'typeId' => $entryType->id,
    'fieldLayoutId' => $entryType->fieldLayoutId,
    'authorId' => 1,
    'title' => 'My Entry',
    'slug' => 'my-entry',
    'postDate' => new DateTime(),
]);

// search categories and retrieve therir ids
$categorySlugs = ['cat1','cat2','cat3'];
$craftCategoryIds = [];
foreach ($categorySlugs as $cs) {
    $craftCategoryIds[] = Category::find()->wpSlug($cs)->one()->id;
}

// get a an asset to be used as a featureImage
$featureImageId = Asset::find()->myField('123')->one()->id;

// Set the custom field values (including Matrix)
$fieldValues = [
    'summary' => 'Some "summary" custom field value...',
    'categories' => $craftCategoryIds, // <-- this works, categories are assigned
    'featuredImage' => $featureImageId, // <-- doesn't work, featured image is not set
    'matrixField' => [
        'new1' => [
            'type' => 'blockTypeHandle',
            'fields' => [
                    // the block's custom field values...
            ],
        ],
        'new2' => [
            'type' => 'blockTypeHandle',
            'fields' => [
                    // the block's custom field values...
            ],
        ],
    ],
]);

$entry->setFieldValues($fieldValues)

// Save the entry
Craft::$app->elements->saveElement($entry);

That's because you have to insert an array of ids rather than a single id

$craftCategoryIds

is an array.

$featureImageId

is an integer. Even if you have just a single element you need to insert an array

'featuredImage' => [$featureImageId]

will work


how to uninstall a plugin when there is no cp option I want to uninstall a plugin.
I disabled it in CP but there is no option to uninstall this plugin.

So I go to composer and remove it from the required section and run composer update.
This deals with the files but not the database record.

So it's not clear to me the best way to uninstall a plugin in Craft 3. Thru the interface is fine when it works but when there is no option how do you get rid of it?

It isn't possible to uninstall a disabled plugin; you'll need to first enable the plugin, and then the Uninstall option will be available.

The correct way to remove a plugin is actually to first Uninstall it. After uninstalling, you can either run composer remove vendor/plugin-handle from the command line, or select the "Remove" option from the Control Panel (the "Remove" option is available for any plugin that isn't currently installed).

If you do it the other way around – i.e. remove the files before uninstalling the plugin – you're probably going to see some issues.


Update billing details for a subscription The Craft Commerce config allows you to set updatebillingdetailsurl. The docs say,

The URL for a user to resolve billing issues with their subscription.

There’s an example of this in the example templates that come with Commerce and this uses getBillingIssueResolveFormHtml().
However, rather than resolve an issue, what I’m looking for is a way for customers with a subscription (via Stripe) to be able to update their billing information before there is a billing issue. Often customers realise their card has expired or want to change their card before the subscription renews, especially as we send emails to notify them about renewals. What’s the best way to create that form, or allow someone to do that?

I've solved this in the past by just showing the payment sources, and allowing the user to delete existing payment sources:
{% set paymentSources = craft.commerce.paymentSources.getAllPaymentSourcesByUserId(currentUser.id) %}

{% if paymentSources %}

                    Card details

                    Actions

        {% for paymentSource in paymentSources %}

                {{ paymentSource.description }}

                    <form method="post">
                        {{ csrfInput() }}
                        {{ actionInput('commerce/payment-sources/delete') }}
                        {{ redirectInput(entry.uri) }}
                        <input type="hidden" name="id" value="{{ paymentSource.id }}"/>
                        <button type="submit">Delete</button>
                    </form>

        {% endfor %}

{% endif %}

You can then show a form to add a new payment source:
{% set customer = craft.commerce.customers.getCustomer() %}
{#
    Note: this next line fetches a single subscription - if you support multiple
    subscriptions, you'll need to do it a little differently
#}
{% set currentSubscription = customer.getSubscriptions()|first %}
{% set plan = craft.commerce.plans.getPlanById(currentSubscription.planId) %}
{% set gateway = plan.getGateway() %}

<form method="post" accept-charset="UTF-8" autocomplete="off" novalidate>
    {{ csrfInput() }}
    {{ actionInput('commerce/payment-sources/add') }}
    {{ redirectInput(entry.uri) }}
    <input type="hidden" name="gatewayId" value="{{ gateway.id }}">

    {{ gateway.getPaymentFormHtml({})|raw }}

    <button type="submit">Add card</button>
</form>

This is probably the simplest answer to your question, though you can get creative with how you present the payment sources and the add card form to the user.


Feed Me - syncing asset fields I'm migrating a Craft 2 site to Craft 3 via rebuild. I've copied the assets over to the new site and indexed the upload directory - that all went well.
However, after doing this and working on other parts of the site I discovered that in the Craft 2 site all the assets had a redactor field attached to them. Is there a way in Feedme to copy over this data when the assets don't have the same asset id?
Sean

Of course shortly after posting this I got it working.

Created a feed and used the filename as the unique identifier and voila imported redactor content to images for 2000+ images.


Is it possible to convert string to uppercase? Is it possible to convert a simple string ("Hello World!") to uppercase ("HELLO WORLD!")?

The upper filter is what you are looking for:

{% set var = 'Hello World' %}

{# Print in UPPERCASE #}
{{ var|upper }} {# 'HELLO WORLD' #}

Besides upper there are also some other filters available to modify the capitalization style of your strings. Of course there is the lowercase equivalent lower and additionally there are some Craft exclusive filters available.

  {# Set test strings #}
  {% set strLower = 'this is a test string' %}
  {% set strUpper = 'THIS IS A TEST STRING' %}
  {% set strMixed = 'this Is a TEST stRing' %}

  {# Apply Twig filters #}

upper: {{ strLower|upper }}
 {# 'THIS IS A TEST STRING' #}

lower: {{ strUpper|lower }}
 {# 'this is a test string' #}

  {# Apply filters provided by Craft #}

ucwords: {{ strLower|ucwords }}
 {# 'This Is A Test String' #}

ucfirst: {{ strLower|ucfirst }}
 {# 'This is a test string' #}

lcfirst: {{ strUpper|lcfirst }}
 {# 'tHIS IS A TEST STRING' #}

  {# Combine filters for predictable application #}

ucwords: {{ strMixed|lower|ucwords }}
 {# 'This Is A Test String' #}

ucfirst: {{ strMixed|lower|ucfirst }}
 {# 'This is a test string' #}

lcfirst: {{ strMixed|upper|lcfirst }}
 {# 'tHIS IS A TEST STRING' #}

  {# Examples for possible use cases #}

PascalCase: {{ strMixed|lower|ucwords|replace(' ', '') }}
 {# 'ThisIsATestString' #}

camelCase: {{ strMixed|lower|ucwords|lcfirst|replace(' ', '') }}
 {# 'thisIsATestString' #}


I am trying to have a vertical tab with hidden content In Craft 3, I am trying to build a vertical tab categories using href=#sample and the hidden content id=sample. I am using bootstrap JS as my library. Here is the code I use. I somehow not managed to hide my content, as the method I am using is if and else. Does anyone have any idea? I'm using entry.title for both the href and id. Ignore the onclick, I was trying out something with it.

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

            {% for entry in entries %}
                {% set thumb = entry.singleImage.first() %}

{{entry.text}}

                    Click Here

            {% endfor %}

The problem with this method is that instead of showing one tab-content per href, it is showing all.

You might be better using entry.slug instead of entry.title as there could be spaces in the title.
Or add a filter to the title - e.g. entry.title|kebab  which would remove any spaces.
Also this line:
{% if siteMainUrl.text  == href %} active {% else %} hide {% endif %}

Where is href coming from? Is it to have a different active tab to the initial one?
Typically I use:
{% for item in tabdata %}
   <div class="tab-pane fade {{ loop.index == 1 ? 'show active' }}" id="{{ item.title|kebab }}" role="tabpanel" aria-labelledby="v-pills-{{ item.title|kebab }}-tab">

  </div>
{% endfor %}

Which leaves the first tab active.


Getting assets from an entry programatically I want to get the id of an asset I've set for a feature image on an entry.
To find the entry I'm using the slug as the criteria like so:
$entry = Entry::find()
  ->slug('0002')
  ->one();

In the returned object I'm expecting to see an array somewhere for custom field values listing the asset Id's, but it's drawing a blank
[_behaviors:yii\base\Component:private] => Array
        (
            [customFields] => craft\behaviors\CustomFieldBehavior Object
                (
                    [hasMethods] =>
                    [summary] =>
                    [featureImage] =>
                    [geopolygon] => [{"col1":"11","col2":"22"},{"col1":"11","col2":"2"},{"col1":"3","col2":"2"},{"col1":"","col2":""}]
                    [_customFieldValues:craft\behaviors\CustomFieldBehavior:private] => Array
                        (
                        )

                    [owner] => craft\elements\Entry Object
 *RECURSION*
                    [_attachedEvents:yii\base\Behavior:private] => Array
                        (
                        )

                )

        )

I know this entry does have a featureImage because it shows up in the admin and I can also view it on the frontend. I can also see all other custom values I've saved for the entry. What am I missing here?

In the returned object I'm expecting to see an array somewhere for custom field values listing the asset Id's, but it's drawing a blank

The reason for this is that entry fields are lazy-loaded, meaning Craft only queries the values from the database once you access them using their field handle (or execute the entity query you get through the field handle, like with the asset field). You can change this using Eager-Loading.
Without eager-loading, to get the asset you need to use the field handle (featureImage, in your case) to get an AssetQuery. Then you can use that to get the images (assets) in your field.
$entry = Entry::find()
  ->slug('0002')
  ->one();

/** @var \craft\elements\Asset */
$featureImage = $entry->featureImage->one();

$featureImageId = $featureImage->id;

See Working with assets field data and Querying assets. The object returned by AssetQuery::one() is an instance of \craft\elements\Asset.


modify image contrast In my experience is the build-in process of image transform not too kind to the image quality, even with the highest quality. In my case the brighter tones in the images are lost which means that images have no properly defined edges.
Is there a good possibility to modify images troughout so they don't drop to total white?

Do you know which image driver your instance is using? GD or Imagick? If GD, try changing the driver first to see if that's the case.


Matrix fields within a plugin? I'm just starting to explore the whole power of Craft and I'm really satisfied with its possibilities so far.

But I can't get one thing done, so here's my question:

Is it possible to use matrix fields in my very own plugins? I already finished a form with several fields just as text inputs and stuff but I really need to extend this thing with a matrix field.

Am I just blind and it's documented anywhere or is it a more complicated task than I can imagine at this point?

Thanks for your help.

Jonas

Matrix fields can only be used as custom fields, on an element.

If you really want to use them, you would need to create a custom Element Type (see the resources at the bottom of http://buildwithcraft.com/docs/plugins/working-with-elements), and then create a Matrix field that is associated with your element type’s field layout.


Front end edit required asset Since file inputs are not allowd to be pre-populated, how do i tell craft that a required asset field is already filled in the front end edit form? Can’t seem to figure this one out.

Edit:
Users can create entries from the front end. Those entries have at least one required field which is an asset (image). Creating an entry works fine. However, when editing an entry the user should be able to change the asset as well so we give them the file input too when editing the entry. If they choose to leave that alone the entry couldn’t get saved since the file input stays empty but is still required.

Solved it for now by making the file input hidden first and only changing its type attribute to file (using jquery) once the asset get’s deleted, ajax-style.


Filtering search with checkboxes multiple param querystring I have a series of checkbox like so:

       <fieldset data-role="controlgroup">
        {% for option in craft.fields.getFieldByHandle('area').getFieldType.options %}
            <input type="checkbox" name="area[]" value="{{ option.value }}" class="bg-white h-4 w-4 tickbox template_filters" />
            <label>{{ option.label }}</label>
        {% endfor %}
        </fieldset>

I want to the user to be able to select multiple but only pass through as a single parameter in a query string.
At the moment selecting multiple results in:
http://localhost:8080/directories/case-studies/?area=africa&area=europe&area=asia
Naturally this only filters my results on the last query (asia)

How can I accomplish a search on all three either merging the queries before submission i.e ?area=africa,europe,asiaOR to keep all versions but append the results to merge the query strings?

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

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

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

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

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

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

{# output your entries #}


Cache HTTP and HTTPS seperately using {% cache %} we have a page that can be accessed both via regular HTTP and HTTPS. We now stumbled across an issue that if a page has been loaded via HTTP (and the content has thus been cached) and another user tries to load the same page via HTTPS afterwards, the browser complains about loading non-secure content, as Craft serves the cached content (e.g. URLs to images) that was generated while accessing the page via HTTP.

Shouldn't the {% cache %} tag take the protocol into account when comparing URLs?
Is there a known workaround or best practice for handling this?

Thanks,

Clemens

Something like this would work:

{% if craft.request.isSecure() %}
    {% set cacheKey = 'secure' %}
{% else %}
    {% set cacheKey = 'insecure' %}
{% endif %}

{% cache using key cacheKey %}
    ...
{% endcache %}

See here for more info.


What's the difference between ElementCriteriaModel and DbCommand? Forgive me if this is a stupid or naive question...

I generally think of an ElementCriteriaModel as being a "search object". Specifically, it's a search object which revolves around a specific type of element. The model has attributes like order, offset and limit, which are obviously common terms when conducting an SQL query.

On the other hand, a DbCommand is an object which directly translates to an SQL query. This is far more flexible, allowing you to do things like perform complex joins.

So while I can certainly see some differences, it's hard for me to grasp the finer points of one vs. the other. (I'll admit that typing this has helped me to see it a little more clearly.)

What am I missing/misunderstanding?

DbCommand represents a SQL statement to execute against a database.

ElementCriteriaModel is a model just like any other model in craft/app/models, but it also happens to make it easy to search for Elements in the database.

By setting all of the criteria for the elements you're searching for and calling the find() method, that will invoke craft()->elements->findElements($this);, which in turn will create a DbCommand object custom built for the ElementCriterialModel parameters that you set.

So think of ElementCriteriaModel as an abstraction on top of DbCommand that makes it easy to search for Elements.


Check formatting of text in Redactor This is really a Redactor-specific question, but I wondered if there is a simple way for clients to view what H1, H2 etc. text is formatted as? I currently instruct them to click on the HTML button whilst selecting the text / having the cursor on the text to view what heading the text is, however it would be really nice for them to be able to see what the text is formatted as without having to look at HTML code.

This is the 2nd or 3rd client now that has asked me the same question. I wonder if anyone has experience in providing a cleaner solution?

Thanks

There is a Redactor setting that should do what you’re looking for:

  Stucture
  This settings introduces visual indicators for HTML tags h1-h6 and div, helping users understand the structure of the document.

https://imperavi.com/redactor/docs/settings/special/#setting-structure

Example editor:
https://imperavi.com/redactor/examples/structure/


search result criteria I've hooked up search and if I run a query on 'Second Presbyterian' for example, I get the expected return.

However, if I search for 'Second Pres' I get nothing coming back as a partial match.

Why would this be?

Have a look at the Searching article in the Docs. If you want to list all entries containing a word that begins with "Second Pres", you have to use this search term "Second Pres*".


Registration Form twig add to an usergroup I just started using Craft and I'm a little stuck with a public registration form.
I made a user group and wanted to add these to the saveUser form.

I found  this answer

but don't know where to find this code.

I'm working in a twig file. Do i have to make my own plugin for that? Or do I have to overwrite something?

<form method="post" action="" accept-charset="UTF-8">
    <input type="hidden" name="action" value="users/saveUser">
    <input type="hidden" name="redirect" value="/">
    <input type="hidden" name="userGroups" = "1">

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

                {% for error in errors %}

{{ error }}

                {% endfor %}

        {% endif %}
    {% endmacro %}

    {% from _self import errorList %}

Username

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

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

Email

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

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

Password

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

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

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

I tried adding a userGroups hidden input but that didn't work.

1) You can set the default user group through your admin:

2) Also I'm pretty sure <input type="hidden" name="userGroups" = "1"> needs to be set to <input type="hidden" name="userGroups" value="1"> for it to work but I'd need to test to be sure.


Login form missing styling Does anyone have any clue why my login page is missing styling. Seems like encoding trouble, but this has been perfectly fine before. I also checked the CSS, which has alot of scrambled content... check out the screenshots.

Front end:

Weird CSS file:

For the garbled CSS, you need to disable zlib.output_compression in your php.ini file.

Seems to be a PHP bug.


Pathed URL creation from templated files I've encounterd a problem with URL creation.

In my plugin I have the following.

public function registerSiteRoutes() {
    return [
        'korting/zoeken' => array('action' => '/discount/discount/index'),
        'korting/(?P<id\d+>)-(?P<slug>[a-zA-Z0-9-]+)' => array('action' => 'discount/discount/view',),
    ];
}

Now when I'm at the frontend, I use the following to create the URL :

{{ url('/discount/discount/view',{id:entry.id,slug:entry.slug}) }}

My plugin gets its data from a solarium document, so its no entry.

I would expect that my URL would become neat like :

/korting/124-test-1

but instead I get :

/korting?id=124&slug=test-1

This feature is build in by default in the Yii URL manager, but Craft doesn't make use of it. This is resulting in my problem that Craft doesn't have the abbility to make pathed URLs.

Is there any other way for me to do this?

You can use the ~ (concatenate string) operator to build the URL manually:

{{ url('/discount/discount/view/'~entry.id~'-'~entry.slug) }}


Do Remote Assets (ie. S3) have file paths? New to remote assets, and can't seem to find any information on accessing remote assets via filepath in areas twig can't be used, such as CSS. I'd like to be able to use those same assets in CSS files but can't seem to find them.

For example, if I named my remote Amazon S3 Asset Source handle to 'amazon', and it has sub folders asset/images/template for an example, would there be a way to reach the files in a file path such as amazon/assets/images/template/filename.jpg for use in CSS and whatnot?

Any information would be greatly appreciated. Thanks!

This question is really more about S3 than about Craft. What you need for the assets is not the file path, but the url. And yes, S3 assets do have a url. This page describes the format for the host:

<bucket-name>.s3-website-<AWS-region>.amazonaws.com

They give these examples:

  This URL requests the photo.jpg object, which is stored at the root level in the bucket.

http://examplebucket.s3-website-us-east-1.amazonaws.com/photo.jpg

  This URL requests the docs/doc1.html object in your bucket.

http://examplebucket.s3-website-us-east-1.amazonaws.com/docs/doc1.html


How to display the title of a category based on its ID? I’m passing the ID of a category to a template via a catId query string (i.e. http://example.com/some/path?catId=10).

How do I display the title of that category?

First you’ll need to grab the category ID from the query string, using craft.request.getQuery():

{% set catId = craft.request.getQuery('catId') %}

Then you can fetch the CategoryModel via craft.categories and its id param:

{% set category = craft.categories.id(catId).first() %}

We can’t be sure that the ID was actually valid, so make sure that category is actually set to something, otherwise return a 404 error:

{% if not category %}
    {% exit 404 %}
{% endif %}

Now, to output the category’s title, just do this:

{{ category.title }}

There are a couple ways you can put this all together, depending on whether the page requires a category ID passed to it, or if it’s optional.

If it’s required, we should verify that the catId query parameter was actually set to something right off the bat:

{% set catId = craft.request.getQuery('catId') %}

{# The catId param is required #}
{% if not catId %}
    {% exit 404 %}
{% endif %}

{% set category = craft.categories.id(catId).first() %}

{% if not category %}
    {% exit 404 %}
{% endif %}

{{ category.title }}

If it’s optional, then we should grab the ID from the query string, and then wrap all of the remaining logic in a conditional, so it only runs if there was an ID:

{% set catId = craft.request.getQuery('catId') %}

{# The catId param is optional #}
{% if catId %}
    {% set category = craft.categories.id(catId).first() %}

    {% if not category %}
        {% exit 404 %}
    {% endif %}

    {{ category.title }}
{% endif %}


Convert CMS from SOLO version to PRO I've had to continue with a Craft CMS install somebody else did, now trying to make sense of it.

A client bought a PRO licence, but the CMS seems to still have a SOLO installed. Is there anyway to convert one to another without having down time in the site?

There is no option to upgrade the CMS once you bought the PRO license.

Thanks in advance

Edit: worth noting that clicking "reactivate" results in a "Craft has successfully been upgraded" but does not result in the removal of the "trial" message in the bottom or in added functions.

“Reactivate” is the button you are looking for. Try checking for updates so Craft gets updated license info – the Trial badge sholud go away once Craft realizes that it’s licensed to run Pro. (If not, please contact support@craftcms.com and send in your config/license.key file, and we’ll sort it out.)


Using a Dropdown field in a Matrix to parse a global I have two globals setup for affiliate and compensated type language - using Matrix and a dropdown I'm trying to find a way to let the user add this language in a new block.

I cannot for the life of me get the globals to parse. In my dropdown handle I've made sure to mirror the handle of the globals themselves. Then I'm using something like this:

{% case 'globals' %}
{% set legalContent = block.legalVariables %}

{{ legal.legalContent }}

'globals' is the block handle, 'legalVariables' is the dropdown handle and 'legal' is the global group. I've tried quite a few different variations on this, but it just spits out 'legal.affiliateLegal' which is right, but it won't parse it.

Am I missing something simple or is this not possible with globals?

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

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

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

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

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

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


onBeforeSendEmail event triggered from Commerce_EmailsService I'm trying to access the order and orderHistory model via onBeforeSendEmail event. I can see that in Commerce_EmailsService.php file on line 311 the event is created with those params and passed to onBeforeSendEmail, but when I try to access them from my plugin, they are not there. I thought they would be available in the variables param, but they are not (or I'm doing something wrong here).

Does anyone know if/how I can access those models from onBeforeSendEmail event?

You don't show what code you're trying to use to access the parameters, but something like this should work from your main plugin class:

public function init()
{
    parent::init();

    craft()->on('commerce_emails.beforeSendEmail', function($event) {
        $params = $event->params;

        $craftEmail = $params['craftEmail'];
        $commerceEmail = $params['commerceEmail'];
        $order = $params['order'];
        $orderHistory = $params['orderHistory'];

        ...
    });
}


Craft multisite site without www redirects unwanted to default site I'm working on a multisite Craft CMS 3 website. When I'll go to www.site-a.com (default) and www.site-b.com this works fine. The correct sites and templates are displayed. But if I'll go to site-b.com (without www) I'll redirected to www.site-a.com. The sites are not multilangual and doesn't have a seperated webroot. I'll point the domains to the same webroot. This is how I'll set it up in the general config:

   'production' => [
        'env'                   => 'production',
        'siteUrl'               => array(
            'default'           => 'https://www.site-a.com/',
            'second'            => 'https://www.site-b.com/'
        ),
    ],

In my htaccess I'll force to use to the www domain, like this:

    # -----------------------
    # Force www
    # -----------------------
    RewriteCond %{SERVER_ADMIN} !^dev$
    RewriteCond %{HTTP_HOST} !^localhost$
    RewriteRule ^(.*)$ https://www.{HTTP_HOST}.com/$1 [L,R=301,NC]

What I'll do wrong?

The problem is that the force ww redirect isn't setup correctly. This must be setup like this:

    # Force www
    # -----------------------
    RewriteCond %{HTTP_HOST} ^domain-a.com [NC]
    RewriteRule ^(.*)$ https://www.domain-a.com/$1 [L,R=301,NC]

    RewriteCond %{HTTP_HOST} ^domain-b.com [NC]
    RewriteRule ^(.*)$ https://www.domain-b.com/$1 [L,R=301,NC]

Also both domains must point to the same server.


templatecachequeries entries with of 157.000 characters in query column after enableling querycaching in craft3 I found rows in templatecachequeries with big amount of characters in the query field. I decoded it with base64 and got this as the largest entry:

query_length: 157036

query_decoded:
O:28:"craft\elements\db\EntryQuery":71:{s:8:"editable";b:0;s:9:"sectionId";a:1:{i:0;s:1:"7";}s:6:"typeId";N;s:8:"authorId";N;s:13:"authorGroupId";N;s:8:"postDate";N;s:6:"before";N;s:5:"after";N;s:10:"expiryDate";N;s:17:"

query: TzoyODoiY3JhZnRcZWxlbWVudHNcZGJcRW...(+157.000)

my sql query:

select length(query) as query_length , FROM_BASE64(query) as query_decoded, query
from craft_templatecachequeries
order by query_length desc

why does the unencoded query with a size of 221 characters get encoded to a size of 157036 characters?

turns out it was an error in my TablePlus, it truncated the decoded_query to 221 characters.


Detecting "Login as User" session From a plugin, how would I go about detecting if an admin user is using the "Login as User" feature?

I believe the way to do this would be to have your plugin listen for the onBeforeLogin event.

From inside there, you'd check to see if the there is an existing session craft()->userSession->isLoggedIn() and the current user is an admin craft()->userSession->isAdmin().

If both of those are true, I believe its going to be a pretty safe assumption that an admin just clicked the "Login as User" button.


Trying to Add a Specific Menu Depending on User Group I'm trying to show a menu based on what group a user is in once they have logged in.  However, I'm not having any success.  Here is an example (for one of the groups) of what I have in my _base.html file, which I'm extending in my other pages:

{% if currentUser.isInGroup('advisors') %}

Advisors

Advisors Home

Education

Blog

Events

Nav 5

{% endif %}

Any suggestions would be most welcome!

OK, so enabling the devMode helped point me in the right direction.

First, I needed to change it to

{% if currentUser and currentUser.isInGroup('advisors') %}

Otherwise I was getting an error message when nobody was logged in ("Impossible to invoke a method ("isInGroup") on a null variable").

Then I discovered that the user I was testing wasn't added to any groups!  I could have sworn I set up the user with a group assigned, but apparently not.  :(


No template found when accessing action method per route I want to render a (non-CP) template from an action method in my plugin controller over a route I defined in the plugin base class:

function registerSiteRoutes() {
  return array(
    'myservice' => array('action' => 'pluginhandle/controller/method')
  );
}

The action itself basically just sets some things up and renders the template:

public function actionMethod()
{
    // irrelevant code here...

    $variables = array('info' => 'success');
    $this->renderTemplate('pluginhandle/template', $variables);
}

But when trying to access the rendered template via it's routed url '/myservice', an error message is shown telling the template can't be found.

Strangely, it seems to work if I use the full action url actions/pluginhandle/controller/method instead. But, I want to have nice URLs if I can have them, right?

I tried it using craft()->templates->render('pluginhandle/template') and $this->renderPluginTemplate('pluginhandle/template') even temporarily setting a new templates path but none of them seems to change that.

Can someone please help me out?

I ended up using Jon's function renderPluginTemplate I found at https://craftcms.stackexchange.com/a/7132/6062 which basically implements what's written here: https://craftcms.com/docs/plugins/templates#plugin-template-paths-explained

I wonder why there is no easier function included into craft by default.