Subscription with Craft Commerce I am using Craft Commerce v2 plugin with Craft CMS v3 with one of my site which basically sells kid products.

It's a subscription website and ones some parent subscribe for any kids package, they will charge for a month ( recurring every month ) and then we will send kids package every week for that month.

I am not sure if Craft Commerce is able to handle recurring payments and subscription / membership thing.

Can anyone help me out, what's the possible and best solution for this.

Commerce 2, currently in beta, does support subscriptions, but right now it's only when using the Commerce Stripe payment gateway plugin.

If you're using a different payment gateway that supports subscriptions, you'll have to write a custom Craft/Commerce plugin and you can use the Commerce Stripe one as a starting point.

The relevant Commerce subscription documentation lives here:
 https://docs.craftcms.com/commerce/v2/subscriptions.html


How to render plugin templates in Craft CMS 3? I cannot find a way to render templates from a plugin controller in Craft 3. I feel as though I've tried every variation advised online but for some reason this still isn't working.

<?php

namespace abc\members\controllers;

class LoginController extends \craft\web\Controller
{
    public function actionForm()
    {
        $this->renderTemplate('abc-members/login.html');
    }
}

The plugin handle is "abc-members".

The plugin has a "templates" directory with "login.html".

I've tried the following, with and without the .html extension, but none can find the template:

$this->renderTemplate('abc-members/login.html');
$this->renderTemplate('abc-members/templates/login.html');
$this->renderTemplate('abc-members/src/templates/login.html');
$this->renderTemplate('abc/members/src/templates/login.html');
$this->renderTemplate('plugins/abc/members/src/templates/login.html');

The following works fine but then I cannot include templates from the installation's main template directory.

<?php

namespace abc\members\controllers;

class LoginController extends \craft\web\Controller
{
    public function actionForm()
    {
        \Craft::$app->view->setTemplatesPath(__DIR__ . '/../templates');
        $this->renderTemplate('login.html');
    }
}

Any suggestions as to where I'm going wrong? I find the Craft 3 docs are a bit lacking in the whole area of plugin controllers, routing and templates other than in the Craft 2 => Craft 3 upgrade guide.

Thanks

After becoming more familiar with Craft and Yii, I've found a more appropriate solution for my use case. I have a couple of ideal requirements:

Templates are stored in a directory within my module or plugin.
Templates can be mixed with general application templates (e.g. my module or plugin template can extend from a general site layout template).

It turns out that the Template Roots functionality enables this, so it is documented but for some reason I was overlooking this previously.

You can simply register the template root during plugin/module init like so:

Event::on(View::class, View::EVENT_REGISTER_SITE_TEMPLATE_ROOTS, function (RegisterTemplateRootsEvent $event) {
   $event->roots['_my_prefix'] = __DIR__ . '/templates';
});

Then templates in the defined directory can be rendered using the defined prefix (_my_prefix in this case), as though that directory exists in the main templates directory. This means they can be used in any context and extend or include templates in the main directory ‒ desirable for app specific plugins/modules.


White screen during installation I am trying to get Craft running on the Digital Ocean/ Serverpilot combination I've seen recommended here. Serverpilot is installed on the droplet and running fine. I created an app, uploaded the most recent version of Craft and unzipped it on the server. I renamed htaccess to .htaccess and put the db credentials in db.php.

I get a white screen on example.com and example.com/admin.
So I tried the alternate URLs recommended in Crafts installation guide, still white screen.

I also tried playing around with the omitScriptNameInUrls setting. No luck.

I also tried adding RewriteBase / to my .htaccess file.

I get this in the Apache access log: 82.156.127.145 - - [03/Mar/2016:01:45:59 -0500] "GET /admin HTTP/1.0" 500 -
82.156.127.145 - - [03/Mar/2016:01:46:00 -0500] "GET /admin HTTP/1.0" 500 -

This is in the Nginx access log: 82.156.127.145 - - [03/Mar/2016:01:46:00 -0500] "GET /admin HTTP/1.1" 500 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/601.4.4 (KHTML, like Gecko) Version/9.0.3 Safari/601.4.4" "-" 1072 0.014 "0" "0.014" "museumrotterdam.nl"

This is in the PHP access log: 82.156.127.145 - [03/Mar/2016:01:45:59 -0500] "GET /index.php?p=admin" 500 0 - 14106 17679 0.013 3407872 154.23% 0.00% "/admin"
82.156.127.145 - [03/Mar/2016:01:46:00 -0500] "GET /index.php?p=admin" 500 0 - 14106 17679 0.012 3407872 82.35% 0.00% "/admin"

There's nothing in the server's error logs.

When I add 'devMode' => true, to the config Craft does not log any errors.

What else could I try?

Whenever I've had a completely white screen from Craft I've traced it to a syntax error in one of the files in craft/config, so I'd double-check your db.php and general.php if they've been edited.


Deployment of Craft 3 site to the production server I am quite new in Craft CMS 3. I have developed a new site and now I want to move it to the production server. I have just moved all the files by FTP, moved the database, changed .env variables.

But when I go to the URL I get a message: "Forbidden You don't have permission to access / on this server."

If I go to URL/web then I get the first page but without images.

URL/admin shows "Not Found The requested URL /admin was not found on this server."

How do I deploy the site? I cannot find a good article/help about deployment for Craft 3.

This looks like a well visited question, its easy as something like this with apache2:

<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html/web/

        <Directory /var/www/html/web/>
           Options FollowSymLinks
           AllowOverride None
           Require all granted
        </Directory>
</VirtualHost>

This is just a sample vhost file, but the real important part here is that you have the web folder set as your document root. This of course wont help anyone not using apache.


Craft 2 FormBuilder 2 equivalent plugin in Craft 3 Is there any plugin equivalent to Craft 2 FormBuilder 2 plugin in Craft 3? My Craft 2 website forms are built with FormBuilder 2. I upgraded the website to Craft 3, but FormBuilder 2 is not working. I need an equivalent plugin to work in Craft 3.

There are a large number of form plugins in the Craft plugin store. See: https://plugins.craftcms.com/categories/forms

Some options:

Solspace Freeform
Solspace Express Forms
Sprout Forms


Craft strips out parenthesis in file names. Is there any way to allow () in asset file names (ex. file(1).txt)? Craft strips it out when it saves. The only way I've found is to change it via ftp and update asset indexes.

I've set convertFilenamesToAscii => false but that didn't help.

I can't see a way... uploads ultimately get run through FileHelper::sanitizeFileName(), which has a hard-coded list of disallowed characters in a file name (including parenthesis).

https://github.com/craftcms/cms/blob/develop/src/helpers/FileHelper.php#L128-L166


A plugin to validate a field depending on another field's value I have an Assets field which I want to be required only if a separate Lightswitch field on the same Entry is 'on'. I'm currently trying to implement this with a simple plugin that creates a custom field type (along these lines).

However, in my Field Type's validation() method I can't work out how to access the Lightswitch field's value on this same Entry, in order see if it's 'on' or not.

In your FieldType you have $this->element available, representing the Element the field is in. If you use $this->element->lightSwitchHandle you can access its value.


Is it possible to get a transformed image's file size (bytes, not dimensions)? I'm using a transformed image in a context where there's a maximum file size. Is there a way to determine the transformed image's file size in the templates? .size can't run on the url string

I don't think it's possible to get the file size of an image after it's been transformed with Craft's out-of-the-box image transforms.

It looks like the .size property only works on the original asset file.

Even if you did something like this...

{% set image = entry.myAssetField.one() %}

{% set thumb = {
    mode: 'crop',
    width: 100,
    height: 100,
    quality: 75,
    position: 'top-center'
} %}

{% if image %}

  {% do image.setTransform(thumb) %}

  {{ image.width }} x {{ image.height }} = {{ image.size }} bytes

{% endif %}

.height and .width properties will show the transformed dimensions (100 x 100), but .size outputs the original file size, not the transformed size.

I'm guessing this might be a problem for Craft because the transformed image may not have been generated before the template is rendered.

Update

The Imager plugin has a getSize method that should work. Imager transforms are created before the template is rendered.

getSize($unit='b', $precision='2') [float]

{{ image.getSize() }} B
{{ image.getSize('k') }} KB
{{ image.getSize('m', 10) }} MB
{{ image.getSize('g', 10) }} GB


Is it possible to bcc/cc an admin on every system email? My understanding is that the testToEmailAddress config items replaces the to address for system emails.

Is there a way, outside of extending the system functionality with a plugin, to add a to/cc/bcc address for system emails? (Use case: I want to CC/BCC an admin on every system email.)

You can easily do that without any plugin by using a transactional email provider like https://mandrill.com/ or http://sendgrid.com/


Live preview option not working for multi-site functionality I am working on a site which has the multisite concept. Each site has its own base URL. The issue is that, if I have logged in to the admin with the primary site and access the preview option for the secondary site in the system then it is showing the cross-domain error in the console of the browser.

Is there any way to solve the issue?

Essentially you're looking for this feature request: https://github.com/craftcms/cms/issues/1160

That has been resolved in https://github.com/craftcms/cms/commit/1ab6b6e6e3cd5a13c949d113c8367e7faf930ee4 which will be released in Craft 3.1.


Images not saving to images folder in web directory I have been following along the Up and Running with Craft 3 tutorial on craftquest.io

I created the assets volume as directed with the absolute file path

/c/xampp/htdocs/craftCMS/craftetest/web/images/drinks

I created the drinkImage field as directed. Put it in the entry type.
Created some entries and uploaded images in the drinks image fields no problems.

The problem is they don't show up in the /web/images/drinks folder at all.
Is there something I am missing?

The solution I found was to start the path with an uppercase C and colon :

C:/xampp/htdocs/craftCMS/craftetest/web/images/drinks


Use alias for site url based on root url defined as env var? I was wondering if the following setup is a good practice.

In my .env file I defined a single rootUrl var which contains the site root url like this:

ROOT_URL="https://www.mydomain.test"

In the general.php config file i've created an alias (@rootUrl) that contains the ROOT_URL env var value:

'aliases' => [
        '@rootUrl' => getenv('ROOT_URL'),
    ],

Then I define my craft sites as following (multilingual site), each site BASE URL is constructed with the rootUrl and a language:

Advantages

You don't have to define every site (language) in the code, languages are managed through the cms (in case of multisite setup, you should define a ROOT_URL for every site).
the @rootUrl alias can be used as part of the resource path in the templates.

Disadvantages

Could this also resolve in a caching issue (like the @web alias)?
...

Does this logic makes sense or is it generally a bad idea to use aliases for the site BASE URL setting?

Thanks in advance

Good practice imo, it's what I do as well. Values come from the .env vars, and for things that are URLs or paths, I make aliases out of them to take advantage of what you're showing above.

This cannot cause any kind of issue like @web -- the only thing wrong with @web is that the host name is computed dynamically, potentially from untrusted browser data.

You're not doing that here, you are explicitly providing the host name, so it's totally fine. You could even do:

'aliases' => [
        '@web' => getenv('ROOT_URL'),
    ],

...to redefine the dynamically generated @web alias to something that is from a static value for the URL.


Template loads via jQuery .load(), but no {% js %} tags are included Inside of a modal window I'm loading a form template via jQuery .load. For reasons I don't know, the {% js %} tags that need to come with the form template are not being loaded, even though the {% js %} tag is placed at the bottom of the loaded partial.

Here's the loading code

{% js %}
  MicroModal.init()

  $(document).ready(function() {
    $('.trigger').click(function() {
      event.preventDefault();

      MicroModal.show('addressModal');
      $('.c-modal__content').load('account/profile/billing/add #newAddressForm');
    });
  });
{% endjs %}

On click a modal will open, retrieve the template, look for the #newAddressForm ID element, and an address form template  will load within it. The HTML part of the form loads fine, but no JS is brought with it.

The loaded partial template:

<form method="post" id="newAddressForm">
  <input type="hidden" name="action" value="commerce/customer-addresses/save">
  {{ csrfInput() }}

  {% include "shop/_inc/addresses/form" %}

  <button type="submit">Save</button>
</form>

And lastly, the {% include %} has the form fields and {% js %} tag inside.

To reiterate, the HTML of the form loads fine. The JS does not come with it. I'm not sure if this is an issue with Twig, Craft, or jQuery. Help would be appreciated!

In Craft 3, the {% js %} tag places the javascript code just before the closing </body> tag in the rendered HTML document by default.

This means that the rendered <script> tag will not be in the #newAddressForm element, but will be rendered just before the closing </body> tag.

So if you are loading the rendered template using jQuery's .load() function and specifying the #newAddressForm element, the <script> tag will be excluded from the injected code as it isn’t within the #newAddressForm element.

Your best bet is to inline the <script> tag within the Twig template rather than using the {% js %} tag to include it. That way you can ensure that the code will be included in the #newAddressForm element as you need it.

More details of the {% js %} tag can be found in the Craft 3 docs: https://docs.craftcms.com/v3/dev/tags/js.html


What's the best way to setup a conditional to see if a matrix block is used? I need to add some javascript to a page depending upon whether or not a matrix block is used, one is for a slideshow block to load responsiveslides.js, another is for a video block to load fitvid.js. If I place it in the loop then I will get the javascript repeated for each time an entry uses that matrix block. I'm looking to add this towards the bottom of the template and load the .js files once each if the block is used in a loop above. What's the best way to do this?

I would use a loop to set a conditional, and then check it afterwards. You need to initialize the conditional outside of the loop, otherwise it won't be set outside the loop later.

{% set haveAVideo = false %}
{% for block in matrixBlocks %}
  {% if block.type == 'video' %}
    {% set haveAVideo = true %}
  {% endif %}
{% endfor %}

{% if haveAVideo %}
  {# video block js #}
  {% includeJsFile ... %}
{% endif %}


Filter events by owner fields - Calendar plugin I'm using Michael Rog's Craft Calendars plugin.

I'm wondering if it's possible to limit events to specified owner category.

For example, I have a training entry with trainingType and trainingLevel category type fields.

While listing events is it possible to do something like:

{% set params = {
    calendar: 'myAwesomeCalendar',
    dateRangeStart: 'today',
    dateRangeEnd: now|date_modify("+1 month"),
    owner.trainingType = 'webinar',
    owner.trainingLevel = 'expert'
} %}

{% for e in craft.calendars.events(params) %}

{{ e.owner.title }}

Starts: {{ e.startDate  | date("Y-m-d") }}

{{ e.owner.trainingType }} , {{ e.owner.trainingLevel }}
{% endfor %}

If not, how else would you approach this.

You can find info about how to do this in the docs: https://calendars.docs.topshelfcraft.com/guide/events-variable.html#How-it-Works

The EventCriteriaModel given by craft.calendars.events is used to query the owner elements from which the event instances are generated.

So, in your example above, you can use something like:

{% set params = {
    calendar: 'myAwesomeCalendar',
    dateRangeStart: 'today',
    dateRangeEnd: now|date_modify("+1 month"),
    trainingType: 'webinar',
    trainingLevel: 'expert'
} %}

This tells Calendars:

Find entries where trainingType is "webinar" and trainingLevel is "expert"...
...and if those elements have any event rules registered on the Calendar called myAwesomeCalendar...
...return the instances of those events that occur in the next month.

(In this case, Calendars queries Entry elements, since that is the default. You could specify a different element type, however.)


How to pull out all user data in a template? I'm trying to pull out user data in a template for specified user profiles whilst the current user is logged in. To do this I check on the userId being referenced and use:

{% if userId != currentUser.id %}
    {% set userProfile = craft.users.id(userId).getContent() %}
{% endif %}

This returns a user object for that user. However when I try to reference any of the fields custom or otherwise for the userProfile it returns blank apart from on userProfile.id which returns the id of the required user.

So what am I missing? I was under the impression that getContent() would pull out all custom fields and these could simply be accessed by using the dot syntax? Or does this only work on currentUser?

Cheers

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

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

Hope it works.


Environmental variable coming back as literal braces I have my general config file set up as follows:

return array(
  'localhost' => array(
  'devMode' => true,
  'environmentVariables' => array(
    'baseUrl' => 'http://localhost:8888/path/to/site/'
  )
 );

Then, I have an asset source set up as follows:

File Base Path: assets/img/general/
URL: {baseUrl}assets/img/general/

The assets pulled within a template get this error:

GET http://localhost:8888/path/to/site/%7BbaseUrl%7Dassets/img/headers/image.jpg 404 (Not Found)

I've used this format with several other sites before, and haven't had a problem. Does anyone have any suggestions?

Your config/general.php file code has some problem with it.

You're missing a closing ) for an array, which I suspect is a typo, but the issue to your real problem is probably the fact you're missing the required '*' key for multi-environment configs to work properly.

See the first warning note on this page: https://craftcms.com/docs/multi-environment-configs


Search Filters Results Unexpectedly This question is related to: SuperTable Returning Unexpected Results w/ Template, which is still unresolved.
In essence, Im trying to return the results of a Supertable at two different points in my template.
{% set featuredContributorsGrouped = entry.contributors
    .search('terms')
    .all()
    |group('contribution[0]')
%}

Appears in my template first, but when I try and reuse entry.contributors.all, it seems like it is already filtered by terms. This happens even if I recast entry as another temporary variable.
I was able to get around this by saving the full results as its own temporary variable before filtering it, but perhaps I'm not understanding how Craft queries modify entry information. I would assume it would be non destructive?

This is a change in behaviour from Craft 2 to Craft 3 and here is the explanation.
In short, you need to clone your query (docs) - see this post for more info.


Check and remove repeat entries from loop Is it possible to loop through the list of entries and filter out any that have the same ID as any of the other entries (duplicates)? I have a specific case where this is an issue. I want to keep the first entry, but filter out the rest of them. I'm thinking it might work something like this...

  {% for event in events %}
    {% IF FIRST INSTANCE OF ENTRY %}
      {{ event.title }}
    {% endif %}
  {% endfor %}

I'd probably try to filter those out in your initial query, but if you've already got them, something like this should work:

{% set existingIds = [] %}

{% for event in events %}
    {% if event.id not in existingIds %}
        {{ event.title }}

        {% set existingIds = existingIds|merge([event.id]) %}
    {% endif %}
{% endfor %}


Login grayed out, logins rejected We have web site with CraftCMS Pro 2.6.2930. Due to development of new site, we set test web server (Centos/Apache/mariaDB) in our local network and migrated whole site there for testing (2.6.2993 with trial license). Site is working, but logins to craft admin webpage are rejected (log in button is greyed out).

For migration i have followed this Migration of Craft CMS from one host to another (we deleted license.key file)

Craft/storage/runtime/logs shows

2018/05/17 13:45:58 [warning] [application]  tried to log in unsuccessfully.

Site content is migrated successfully.

PS: I've already tried this and it isn't working: Reset password with MySQL

Any ideas?

PS: It seems my problem is very similar to this one Control Panel access. Greyed out button since i see (almost the same) errors

Resolved! So, the console clearly showed which files were broken.

I've downloaded those files again from production server, and uploaded on my test server. Login succeed without any problems now!

I guess it has something to do with transfer mode (auto, binary, text etc) when transferring files via FTP. Transfer mode should be on auto, otherwise files might get corrupted which can cause all kind of (weird) problems. Thanks to Brad for help!


Look up a specific Variant, using the variant's ID? When looking up a specific product by ID, you'd do something like this:

{% set product = craft.commerce.products.id(productId).first() %}

If you instead have a variant ID and want to find a specific variant, what is the Variant equivalent of that code?

You can use the recently documented template variable:

craft.commerce.variants.id(yourVariantId).first()

If you want to get a variant's product from the variant ID, you can use:

craft.commerce.products.hasVariant({id: yourVariantId}).first()

https://craftcommerce.com/docs/craft-commerce-products#hasvariant


How to filter relational field types on their related content's status? I have a Matrix field on Users. In that Matrix field is an Entries field. I need to pull all Entries from that field, regardless of the related Entries status.

The following code returns Users but the Users' anEntryField only shows the default 'live' entries.

{% set users = craft.users({
    with: [
        'myMatrixField:blockType.anEntryField'
    ]
}) %}

How do I pass status(null) to that field? Or, if it's actually getting all the Entries... how do I show them all?

I have tried:

{% if
    user.myMatrixField | length
    and
    user.myMatrixField.first().anEntryField.first() | length
%} ... {% endif %}

But nothing in that block is executed for users who's anEntryField contains an entry that is disabled or expired.

My assumption that the query was not getting all the related entries from withing the Matrix was wrong. The filtering that happens is applied at output level, and not the query level.

The solution is to tell craft that you don't care about the status of any linked anEntryField entry as part of the if...

{% if
    user.myMatrixField | length
    and
    user.myMatrixField.first().anEntryField.status(null).first() | length
%}
...
{% endif %}

In this example the result will be the first myMatrixField block with a status of 'enabled' (that's the default filter), and fetching from that first Matrix result the first related Entry on the anEntryField regardless of the status of that related entry.

That's what I was after.


htaccess www to non-www redirect (and config.php) I need to set up a redirect from the www version of my site to the non-www version for SEO. I found a solution that would work here if it weren't for the fact that it breaks the index.php redirect that comes with craft.

Can anyone tell me how to implement a generic redirect from http://www.site.co.uk to http://site.co.uk and still keep the index.php craft redirect working?

Additionally, does this affect the config.php file, or does that get loaded AFTER the redirect?

Thanks!

Providing you have the necessary permissions to do this, the following in your .htaccess should do the job:

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

In place, the full file will probably look something like this:

<IfModule mod_rewrite.c>
RewriteEngine On

# Redirect to non-www domain
RewriteCond %{HTTP_HOST} !^domain\.co\.uk$ [NC]
RewriteRule ^(.*)$ http://domain.co.uk/$1 [R=301,L]

# Send would-be 404 requests to Craft
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
RewriteRule (.+) index.php?p=$1 [QSA,L]
</IfModule>

The following seems to work for me as a generic option:

<IfModule mod_rewrite.c>
RewriteEngine On

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

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

# Send would-be 404 requests to Craft
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
RewriteRule (.+) index.php?p=$1 [QSA,L]
</IfModule>


Is there a way to merge multiple Plain Text fields into a Matrix or Table field? I have a site we are importing into Craft (using https://github.com/boboldehampsink/import/) and it has about 10 fields setup called feature1, feature2, ... feature10 that are Plain Text. After I import them, rather than leave them all as individual text fields, is there a way to merge them into a matrix block or table field?  I have the data in a CSV as well that I am using for the import.

You can obviously perform your import directly from the CSV files (or remote database), reformat the data and then import; or import the data into temporary craft text fields and then in a separate operation, move the data in craft. Personally I would opt for the first solution to avoid the extra work of creating temp fields (and allow me to import again later if needed).

This example is for importing into a table field (importing into a matrix field would be quite different and slightly more complicated).

// loop through each row in your CSV file or results on external database query
foreach($result as $row)
{
    $entry = new EntryModel();
    $entry->sectionId   = 1;
    $entry->typeId      = 1;
    $entry->authorId    = 1;
    $entry->enabled     = true;

    // create temp array to store feature data
    $myTableFieldData = [];
    array_push($myTableFieldData, array("col1" => $row['feature1']));
    array_push($myTableFieldData, array("col1" => $row['feature2']));
    array_push($myTableFieldData, array("col1" => $row['feature3']));
    // ...

    $entry->getContent()->setAttributes(array(
        'myTableFieldHandle' => $myTableFieldData,
    ));

    // if you want to check the data first before importing
    // uncomment this and comment out saveEntry below
    //var_dump($entry);

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

    if (!$success)
    {
        $errors = $entry->getErrors();
        foreach ($errors as $error) {
            MyImportPlugin::log('Error:'.$error[0], LogLevel::Error);
        }
    }
    else
    {
        MyImportPlugin::log('Successfully saved entry "'.$entry->id.'"', LogLevel::Info);
    };

}


Address form not redirecting to payment form in Craft Commerce I've had this working before but with the billing address as well. Do both the billing and shipping addresses need to be filled out in the same form for this to work? I get this error when I click the submit and the page just refreshes instead of redirects.

  CWebUser.flash.error' => 'Cart not completely updated.',

Here is my code

<form method="POST" class="flex-container flex-center flex-col nav-buttons flex-lg">
    {{ getCsrfInput() }}
    <input type="text" name="email" value="" placeholder="email@site.com"/>
    <input type="text" name="shippingAddress[firstName]" value="" placeholder="First Name">
    <input type="text" name="shippingAddress[lastName]" value="" placeholder="Last Name">
    <input type="text" name="shippingAddress[address1]" value="" placeholder="Street Address">
    <input type="text" name="shippingAddress[address2]" value="" placeholder="Apartment/Suite/etc">
    <input type="text" name="shippingAddress[city]" value="" placeholder="City">
    <input type="text" name="shippingAddress[zipCode]" value="" placeholder="Zipcode">
    <input type="hidden" name="shippingAddress[countryId]" value="233">
    <select style="width:100%; padding:10px 0; margin:10px 0; text-align-last:center;" name="shippingAddress[stateId]">
        <option>State</option>
        {% for stateId, stateName in craft.commerce.statesArray["233"] %}
            <option value="{{ stateId }}">{{ stateName }}</option>
        {% endfor %}
    </select>
    <input type="hidden" name="action" value="commerce/cart/updateCart">
    <input type="hidden" name="redirect" value="store/checkout/payment">
    <input type="submit" value="To Payment">
</form>

I extended my code to include the billing address and it worked. So I guess the answer to my question is yes, shipping and billing address need to be submitted together.


Creating a custom, "multiple dates picker" field We're migrating* a website that uses http://dubrox.github.io/Multiple-Dates-Picker-for-jQuery-UI/ to store any combination of dates for an entry... (eg not just a single date or date range, can be lots of individual dates which aren't sequential)
What would be the best kind of field/setup to import these into?
I guess we could create a custom field type that implements the same multipicker as above as it's also based on the jQuery datepicker widget... but have never created a custom field type from scratch though... what is the best approach to this?
(*7000 entries to import via FeedMe, looks like every single date is added to an event table as an individual row and looked up via an id :zany_face:)

Instead of creating a custom field could you do it with a Matrix with each date going into a matrix row?
I've done something similar in the past for scheduling delivery dates for a Commerce order. Each order has a matrix field for delivery dates and each date (along with some other data) is added as a separate row.


Incomplete localization of `{{ entry.postDate.diff(now)|duration }}` In a Dutch site, when I output {{ entry.postDate.diff(now)|duration }}, the result is something like 5 dagen, 3 uren, 43 minuten, and 42 seconden. Why is the English "and" not localized? My understanding (I don't speak Dutch) is that "and" should be "en" in Dutch...

Am I missing some crucial step here? Thanks!

Because neither Craft (nor Yii) provides a default Dutch translation for the word "and".

https://github.com/craftcms/cms/tree/develop/src/translations

https://github.com/yiisoft/yii2/tree/master/framework/messages

You can provide your own translations using Craft's static translations feature, though: https://docs.craftcms.com/v3/static-translations.html


Is There a Way to Add Tabs in Global Fields? I see that it is not possible to add tabs to Global fields (unlike, say, with entries, where one can organize one's fields into different tab groups).

Is there a way (without editing the core files) to change this so that I can organize my global settings fields into tabbed sections?

Thanks.

As far as my knowledge goes there is not a way to do this without some though changes.
Wouldn't it just be better to add another global and just name it settings?

Something like:

globalSettings(option1)

globalSettings(option2)

globalSettings(option3)

So that you organize them like that? Only thing you have to keep in mind then is when you use it in your template you have to keep track of which setting is used for what but if you name them right that wouldn't be an issue.


FeedMe - Extracting attribute from an RSS feed field So I'm using FeedMe to get RSS atom feeds and this is working O.K. But there's this field that has an attribute I want to extract. And I cannot get this to work.

In the FeedMe documentation it says:

For example, the XML <field my_attribute="Some Value">Another Value</field>,
you can use {{ xml.field.attributes.my_attribute }}.

My field is called 'enclosure' and has an attribute called 'url' that I want to extract. According to the documentation, one would assume that this should work:

{% set feed = craft.feedme.feed(myfeed_rss) %}

{% for node in feed %}

    {
        'title': {{ node.title | raw }},
        'description': {{ node.description | raw }},
        'url': {{ node.link | raw }},
        'date': {{ node.pubdate | raw }},
        'image': {{ node.enclosure.attributes.url | raw }}
    }

{% endfor %}

Namely {{ node.enclosure.attributes.url }} should work? All the other fields are collected correctly. So it's just this one.

Edit: Btw, the feed I'm using is this one.
http://www.adressa.no/?widgetName=polarisFeeds&widgetId=3185248&getXmlFeed=true

Edit2: Managed to get it to work, with help from crafw. Some of the nodes weren't empty, fixed it by changing the line to:

{{ node.enclosure.attributes.url|default('empty') }}

https://craftcms.stackexchange.com/users/632/crawf

I'm unable to view the feed via the link you've provided - seems like it may not allow public access. In any case, see a working example below using an example public RSS feed.

{% set params = {
    url: 'http://www.feedforall.com/sample.xml',
    type: 'xml',
    element: 'item',
} %}

{% set feed = craft.feedme.feed(params) %}

{% for node in feed %}
  {{ node.category.attributes.domain }}
{% endfor %}


Display entries filtered by one or two related entry fields ordered by "dateUpdated" I think I have been staring at this one too long because conceptually it seems fairly straightforward but I can't seem to pull it off. I am pretty sure I am going nowhere due to how complicated I am making my twig code

Here is what I have:

"News" channel that holds news entries that can be optionally related to either a Program 1 entry or Program 2 entry.
Program Type 1 channel.
Program Type 2 channel.
In the news entry there are two fields, one to relate Program 1 entries to the news item and another to relate Program 2 entries to the news item. They are being used similarly to categories in this case.
News entries can have one or both of the related entries fields populated
This is in a module that is shared throughout the site so I am not on a "news entry" page (if that makes sense), it will be an include that is included where needed.

Here is what I need to do

I need to be able to display a list of:

the four most recently updated Program 1 or Program 2 NEWS items (combined list order by dateUpdated)

Thinking out loud it looks like I can grab a listing of each and then merge them together but I would love to see how smarter folks would handle this in the most efficient way.

If I understand your structure correctly, something like this should work. First grab the ids, merge them (if they don't already exist in the id array), then query for entries based on ids with sort order defined.

{% set programs1 = craft.entries.section('programs1') %}
{% set programIds = craft.entries.section('news').relatedTo(programs1).ids() %}
{% set programs2 = craft.entries.section('programs2') %}
{% set program2Ids = craft.entries.section('news').relatedTo(programs2).ids() %}

{% for id in program2Ids %}
    {% if id not in programIds %}
        {% set programIds = programIds|merge(id) %}
    {% endif %}
{% endfor %}

{% set programEntries = craft.entries.section('news').id(programIds).order(dateUpdated).limit(4) %}

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


entries.onSaveEntry does not fire from frontend I created my own actionEntrySave for my frontend form. and I'm using the $entryService->saveEntry($entry); method to store my entries into the database.The problem is this does not fire

craft()->on('entries.onSaveEntry', function(Event $event) {
    die(var_dump("fired"));
});

When I save/edit the same entry in the backend or create a new one I see an empty page with "fired" there.. (just for testing) and I can manipulate the entry the way I want without any problems. If I do the same in the frontend (saving/editing an entry) the event does not trigger but the entry saves. Can someone explain why?

Thank you very much

edit: I already tried onBeforeSaveEntry with the same result

Edit 2 Solved
I solved it now.. my error was I did this

$entryService = new EntriesService();
$dbInsert = $entryService->saveEntry($entry);

But it has to look like

$entryService = craft()->entries;
$dbInsert = $entryService->saveEntry($entry);

I thought all services were singletons. My mistake

Where is your "craft()-on()" code located?

Per the documentation, the best place is in your primary plugin file in a method named "init()".

https://craftcms.com/docs/plugins/hooks-and-events#listening-for-events

For example, here's mine:

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

    // event triggers
    craft()->on('charge.onValidate', array($this, '_validateRegistrationForm'));
    craft()->on('entries.saveEntry', array($this, '_processEditPricelistLocationForm'));
    craft()->on('entries.saveEntry', array($this, '_processEditGuestUsersForm'));
    craft()->on('entries.saveEntry', array($this, '_processGuestUserAccessForm'));
    craft()->on('entries.onBeforeSaveEntry', array($this, '_processEditGuestRemoveUsersForm'));
}

and here's just showing that I do in fact handle the Event $event in the method:

/**
 * Charge onValidate
 *
 * @param Event $event
 */
public function _validateRegistrationForm(Event $event)
{
    // do stuff
}


Is it possible to adjust Redactor config on a per-user basis? So in the Redactor config file, I have the standard "source" plugin enabled:

"plugins": ["source"]

This is great for the admins who want to go in a play with around with the markup. However, I'd like to avoid certain user types from having that level of control. Essentially I want to stop clients messing with stuff they shouldn't.

Is this possible?

Not possible with the native Rich Text field in Craft (or any field in Craft since the settings aren't defined on a per-user basis).

You could probably pull this off with a custom plugin that added a field type that extended Craft's Rich Text field and overwrote (at least) the getIntputHtml() and getSettingsHtml() methods to add per-user settings support.


Set Password form - use front-end template for admin users I am currently building an intranet. I have created a password reset and a set password form that is used on the front-end. However, admin users get redirected to the 'Craft' set password form. is there anyway possible to make all users use the front-end set password form for consistency?

Thanks.

Not without hacking up some core files, unfortunately.

You can see the logic Craft 2 uses to determine which set password template to render for a given request here: https://github.com/craftcms/cms/blob/develop-v2/src/controllers/UsersController.php#L1702-L1720

Basically, if a user has "accessCp" permissions (which admins certainly do), then they're going to get the Control Panel set password template.


Hosting Craft on Heroku, problems with Asset uploads and thumbnail generation Has anyone had success hosting Craft on Heroku? I got it up and running, but can't get file uploads to work. Also image thumbnails don't get generated. I am using Craft PRO and Assets are hosted on Amazon S3. I understand that you can't upload assets to Heroku, I thought using S3 should be sufficient to circumvent that fact.

I solved the problem by setting the client_max_body_size to, in my case, 20M.

Did this using the following nginx_app.conf

location / {
    # try to serve file directly, fallback to rewrite
    try_files $uri @rewriteapp;
}

location @rewriteapp {
    # rewrite all to index.php
    rewrite ^(.*)$ /index.php?p=$1 last;
}

location ~ ^/(index)\.php(/|$) {
    client_max_body_size 20M;
    fastcgi_pass heroku-fcgi;
    fastcgi_split_path_info ^(.+\.php)(/.*)$;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param HTTPS off;
}


Redactor image button not showing up I have seen a few questions the same as this, but none with answers that work. I am trying to use redactor to allow for dynamic blog posts to be written by my team. In my redactor set up file I have:

buttons: ['html', 'format', 'bold', 'italic', 'deleted', 'lists', 'image', 'file', 'link'],

AND

imageUpload: true

And yet, the button does not show up when I go into my editor.

Any ideas about what else it could be?

It may be that you need to select the redactor config on your field's settings...

Example - say you edited config/redactor/Standard.json

Go into your admin panel, then go to Settings, then Fields.

Open one of your redactor, and scroll down to where you select the field type. When you select Redactor, you get a new option underneath.

And you then select which Redactor Config you want to use.

If you're not seeing it, maybe try clearing your caches. And then double-check that you've saved your redactor config in the right place, and it's got the right file permissions.


Prevent EVENT_BEFORE_VALIDATE in specific case I have a registration form and its custom validation in PHP plugin code.

However, the validation works when user set a new password.
I supposed that $event->isNew is good to detect if it is a new user registration or not, but the element does not work.
Craft says it is unknown property.

Could you tell me how to detect the kinds of submission?

// Registration Form
$request = Craft::$app->getRequest();
Event::on(
    User::class,
    Element::EVENT_BEFORE_VALIDATE,
    function (Event $event) use($request) {
        // If a user already logged in we are not on the public registration page
        if (Craft::$app->getUser()->getIdentity()) return;

        if (!$event->isNew) return;

        // Do the custom validation
        if (!$event->sender->firstName) {
            $event->sender->addError('firstName', Craft::t('yii', '{attribute} cannot be blank.', [ 'attribute' => Craft::t('app', 'First Name') ]));
            $event->isValid = false;
        }
...

First, you should test the sender property pointing to the User element.

Second, there's no such property as isNew in that case.

However, you could test that user is new given that its ID won't be set in case the user has not been saved yet.

Something like:

Event::on(
    User::class, // \craft\elements\User
    User::EVENT_BEFORE_VALIDATE,
    function (\yii\base\ModelEvent $event) {
        $sender = $event->sender;
        Craft::debug("User " . ($sender->id ? "already exists" : "is new"), __METHOD__);
    }
);


Whitespace created a start of HTML I am getting a strange whitespace character when using a different language.

All languages use the same templates/database/plugins etc.
But when I go to any other language except the default I get a whitespace character before the

I have no idea what this is coming form. Its there when I disable all plugins and use a blank template.

I finally found what the problem was.

The translations files (/craft/translations/de.php) were encoded as "UTF-8 with BOM"
I opened these files in Sublime text and saved them as regular old UTF-8, which fixed the issue.


How do I prevent Redactor from wrapping  with I'm looking to have the <img> inserted without the wrapping <p />. I'm assuming I can tie in to one of the callback functions to do this? There is a fileUploadCallback function available but based on nomenclature, doesn't seem like that would help me if I added a path to a remote image versus uploading one.

Has anyone done this yet?

I’m not sure that this is possible – Redactor has some checks in its code to make sure everything lives within a block-level element like <p>.

You might be better off using a Matrix field instead, with Text and Image block types. You can still use a Redactor field within your Text block type; just disable the Image toolbar button on it from your Redactor config in craft/config/redactor/. Give the Image block type an actual Assets field.

Then from your templates you’ll have full control over the image markup.

{% for block in entry.myMatrixField %}

    {% if block.type == 'text' %}

        {{ block.myRichTextField }}

    {% elseif block.type == 'image' %}

        {% set image = block.myAssetsField.first() %}
        {% if image %}
            <img src="{{ image.url }}" width="{{ image.width }}" height="{{ image.height }}" alt="{{ image.title }}">
        {% endif %}

    {% endif %}

{% endfor %}


Trouble with login admin I'm having trouble in the control panel. I'm get logged out all the time and I can't find the reason. The "Your session has ended" modal window appears all the time, I can just do a refresh and it stays in the control panel (logged in). Sometimes i'm also thrown out completely.

What did i tried to solve it (together)

'overridePhpSessionLocation' => true or false doesn't seem to make a difference
removed my cookies
craft/storage/runtime is on 777
removed database content of craft_sessions
removed craft/storage/runtime multiple times, it's created again.
craft/storage/runtime/sessions stays empty and is on 777

This is the error in the log files:

  2016/02/09 20:31:12 [warning] [application] Tried to restore session from a cookie, but the given hashed database token value does not appear to belong to the given login name. Hashed db value: cf349cc791478ab96e9229dad6367f1358f1404bczozMjoiMGQ0SUJxelZYYmdNUVh6WDhVdHhBODFUb0lWb2dGT0wiOw== and loginName: REDACTED

(I edited the question to narrow down the problem. it's kinda driving me nuts)

in the end, for me making

/opt/www/dave/web/tmp

writable for craft was the solution.
thanks for all the feedback!


Paste From MS Word to Redactor Would I be right in assuming to allow clients to safely paste text from MS word into a WYSIWYG all I need to do is add:

pastePlainText: true

to my Redactor json config file? I have done this and it seems to be working but I am aware of the problems concerning MS Word and pasting to wysiwyg's and don't want to encounter them further down the track.

I haven't directly tried this myself, but I believe the answer is yes, you are correct.

To be fair, this is barely even a Craft question... This is 99% about Redactor, and what it is capable of. Skimming the Settings > Clean page of the Redactor docs, it seems like Redactor already takes steps to normalize content from MS Word, and pastePlainText is simply one piece of the puzzle.

Here are some steps you can take to further assess whether you're getting the output you want from your Redactor settings...

Look at how the data is being stored in your database. Specifically, keep an eye on your field's column in the craft_content table.
Try various settings from the Redactor "Clean" options. The developers behind Redactor are clearly aware of MS Word, and all of it's bizarre behavior. If you don't get the results you want right away, try mixing & matching Redactor settings until you get the desired behavior.

Hope that helps!


Include single entry type with custom parameters in the for loop within multiple entry types I have several entry types, where I want to set a special element criteria for the entryTypeHandleX entry type, and simultaneously loop through all entry types included entryTypeHandleX.

The criteria I want to set is to skip first X entries for entryTypeHandleX.

In my template it looks like this:

{# Set ECM for all sections and entry types #}
{% set params = craft.entries.section().types() %}

{# Set ECM for all channels and special entry type #}
{% set special = craft.entries.section().type('entryTypeHandleX').offset(X) %}

{# Set ECM for entries. Check var 'params', Where the data are coming from!!! #}
{% set entries = params.limit(10) %}

{% paginate entries as entriesOnPage %}

{% for entry in entriesOnPage %}
{# entry #}
{% endfor %}

{% endpaginate %}

One way to merge two distinct elementCriteriaModels is to perform each query separately grabbing their 'ids', then merge the 'ids', and perform a new query using the 'ids' as the only parameter.

{% set first10 = craft.entries.type('entryTypeHandle').limit(10).ids() %}
{% set all = craft.entries.ids() %}
{% set first10-All = all|without(first10) %}
{% set entryIds = craft.entries.limit(10).id(first10-All).ids() %}
{% set specialIds = craft.entries.type('entryTypeHandle').offset(10).ids() %}
{% set entryIDs = entryIds|merge(specialIds) %}

{% set entries = craft.entries.id(entryIds) %}
{% paginate entries as entriesOnPage %}
    {% for entry in entriesOnPage %}
        {# entry #}
    {% endfor %}
{% endpaginate %}

I also notice a few other issues in your example, that might be causing you some problems.

I see a lot of empty query parameters which are not needed — keep in mind that empty parameters will not really affect the results. (i.e. craft.entries.section().types() is really the same as just craft.entries, which, in this case, will return all entries).
By modifying an existing query, you are essentially creating two queries to the database, which may not be what you're after.

{% set params = craft.entries.section().types() %}
{% set entries = params.limit(10) %}

This works, but you are essentially querying the database twice, creating two elementCriteriaModels. A better way to do this is to use a parameters array.

{% set params = {
   section: 'mySectionHandle'
} %}

If you later need to add more parameters, you can do so using the merge filter, before running the query. The result is that you will only be querying the database once.

{% set params = params|merge({ limit:10 }) %}
{% set entries = craft.entries(params) %}


Rich Text field won't accept link I am unable to insert a link into a Rich Text field.  The modal opens, I enter the data but nothing happens when I click ‘save’, no errors seem to be thrown.  I am able to insert a link to anther entry in the same modal. Field(s) are set to default and no plugins are being used.  The entries are both in a structure with no urls of their own, and in Craft Commerce product types.

Twas my own fault - I have addTrailingSlashesToUrls set to true and falsely thought it added one after .com/ but was wrong.  As soon as I added / to the link back in order.


Re-Saving neccessary? I have switched the field of the SEOmatic plugin to translateable. All the SEO Titles are taken from the entry title. After changing to translateable I can see the translated fields in the SEO Title field but I need to save the entry again to see that on the website. Until then, the title is just in one language. Why is that? Is there any way to automate that, since I have a hundreds of entries and I dont want to do that manually.

I'm not entirely sure why you need to resave all the entries but I do know how you can do it quickly and easily. I'd recommend using the Walk plugin by Michael Rog to do this.

The plugin is pretty well-documented in the repository README, but I'll outline the steps here for you as well:

Download the plugin folder, drop it in /craft/plugins, and install the plugin in the Craft CP.
Add the yiic file from the repository into the base folder of your Craft install (next to the craft folder).
Open your terminal, cd to your Craft install, and run the following:

php yiic walk entries --section=blog --limit=null entries.save

Obviously replace blog with the name of your section.

Hopefully that does the trick for you! Let me know if you have any questions...


Serving CSS files from template folder Is there a way to serve my CSS files from the templates folder? I am wanting to be able to use TWIG tags, etc to build some of this. And even if the TWIG tag idea does not work out, I would prefer this sort of an organizational structure.

You can, just by naming the file with a .css extension, and then accessing it just like any other template in there. For example, you could have the file craft/templates/styles/styles.css, and that would be accessible from http://example.com/styles/styles.css. Craft will even serve it with a text/css Content-Type header.

However, this is only a good idea in certain situations. Directly loading your CSS by pointing the URL to a publicly-accessible file that Apache can serve without PHP/Craft’s help is going to be much less work for your server (serving static files is what Apache does best). Also, browsers won’t be able to cache those dynamic CSS requests (unless you manually override the cache headers from your template using the {% header %} tag, but then, there would be no point in having it dynamically generated in the first place). So this will have some impact on your overall page load times.

You’d probably be better off just generating your CSS styles that have to be dynamic  right in the main HTML templates within <style> tags, or using the {% includeCss %} tag.


Do I need the web.config file in the craft root directory? I'm working off of a linux machine (Apache) I don't use the web.config that's found in /public/web.config. I will use the .htaccess file.

I am curious if I can remove the web.config file from /craft/ since I am not in a windows environment. I have been removing it, but not sure if that's exactly a great idea...

If you're not specifically running IIS on Windows, then you can safely remove it.


Best practice for adding a title to a channel overview page I have a Blog where everything is on one template. The entries don't have an own url.

{% for entry in craft.entries.section('blog') %}
    {# everything #}
{% endfor %}

Now I want to give this page a title.

I could create a single called Blog page to have a title and a url. But isn't that a bit much for just a title? I hate to have a single with almost no content in the control panel.
Could there be a better way to add a title to that page?

Globals?
Categories?
Something else?

How do you handle that?

If there's only this one page, I'd probably also use a Global Set instead of a Single Section for this.

Add a Global Set with the handle siteInfo and add a Plain Text field title for your title to it, make sure to mark it as translatable. Then in your template access it via {{ siteInfo.title }}.

The good thing with this approach is that you can allow your client to edit the title (for all locales), without having her edit the template or the static translations file. And! You can later add other fields to it, e.g. for other site metadata (description, open graph, etc.) or to change the site's theme.


Invalid Configuration Error in Craft CMS 3 using Nitro 2 I'm getting into Nitro 2 and so far loving it. I decided to create a scaffolding project to jump start other projects. Along the way, I ran into this error:
Invalid Configuration – yii\base\InvalidConfigException
/Users/cbad/websites/nitro/core/cms/web/cpresources doesn’t exist or isn’t writable by PHP.

The path exists and the permissions, look correct. They are drwxr-xr-x. I removed the contents of cpresrouces based on another solution found on google but didn't help. I'm missing something!
I was syncing my .env file and general.php when this began. In .env I made WEB_ROOT_PATH like this:
WEB_ROOT_PATH=/Users/cbad/websites/nitro/core/cms/web/

In general.php I did this:
'resourceBasePath' => App::env('WEB_ROOT_PATH').'cpresources',

If it helps, here are the permissions on the folders. They seem to be the same as those on a site that doesn't get this error:
drwxr-xr-x  2 cbad  staff    64 Mar  7 16:55 assets
drwxr-xr-x  2 cbad  staff    64 Mar  7 16:27 cpresources
-rw-rw-rw-@ 1 cbad  staff   604 Feb  5 20:12 index.php
-rw-rw-rw-@ 1 cbad  staff  1202 Feb  5 20:12 web.config

It seems to resolve to the correct location, but I get the error listed above. Is it obvious what I'm doing wrong?
Thanks!

This path is on your host machine but this isn't how docker sees things. To Nitro, the location of the folder is /app/web/cpresources.
Without going into too much details, I'd recommend going with an alias instead of hard-setting your webroot the way you are currently doing it. Doing so will make your scaffolding just work without having to change this path every time.
In your config/general.php define your webroot alias like this:
'aliases' => [
    'webroot' => dirname(__DIR__) . '/web'
],

You can then remove 'resourceBasePath' => App::env('WEB_ROOT_PATH').'cpresources', altogether since its default value is already correct.
This alias will also be handy for setting things like File System Path on your volumes.


How to add active class to homepage nav list item Someone provided a solution, via the Craft Google community, but it was suggested that I also post it here for others to use.

Home

Work

About

The above was adapted from the demo site install (I think) and although 'work' and 'about' work fine 'homepage' did not.  I used 'homepage' as this is the 'handle' in the craft sections part of the cms so I thought that would be correct.

I initially found this How can I add a dynamic "active" CSS class to the navigation on any given page? but not being that dev focused found the many alternatives a bit confusing.

It was suggested that I add a 'section' to the homepage template and so I added {% set section = "home" %} after {% extends "_layout" %} in the homepage  index.html.

I then amended my first
 from above to be just

Home

which worked as required.

I hope that helps.

If anyone can explain why my original doesn't work, in layman's terms that would be much appreciated.

Thanks

Laurence

Unless the URL is domainname.com/homepage then your class will not get added.

Are you using template layouts? If you are you could have something like this in your _layout

{% block bodyClass %}{% if bodyClass is defined %}
{% else %}
{% endif %}

Then in your home template you would set it like so:

{% set bodyClass = 'CLASSNAME' %}

OR you could something like this in your nav:

Home

Work

About

#

Hopefully that helps. If not you can always look at this post with other methods:

How can I add a dynamic "active" CSS class to the navigation on any given page?


With two EC2 Craft instances, the Control Panel session keeps expiring Things were fine (no session logout for admin from CP) when there was only one EC2 instance for our website.
I created a replica of the existing EC2 instance and now when I go to Control Panel, session keeps getting expired every 30 seconds.
Please help me out in order to resolve the issue.
Also, what are the things I should keep in mind when I'm using multiple EC2 instances for Craft website.

Easiest solution: if AWS supports "sticky sessions" at the load balancer level, then you should enable to to ensure that the user gets sent back to the same EC2 instance that their session was created on.

Next easiest: create an NFS share and use https://secure.php.net/manual/en/function.session-save-path.php on all EC2 shares so all EC2 instances read/write to the same place.  You'd also want to set the Craft appId and validationKey config settings to be consistent across all of the EC2 instances.


Conditional Logic to show or hide fields in the admin? I'm looking for a way to show or hide fields when editing an entry based on items selected.

I need to manage a list of businesses and my plan is to have a channel to hold them all. But based on the type of business, there are different pieces of information I need to collect.

They all have common attributes (Name, Description, Location, Phone, etc.)
There are many types (Restaurant, Recreation, Venue, etc.)

Many types have subtypes, but not all (Restaurant: American, Chinese, Casual)
Some have additional Info based on their type (Venu includes a list of meeting rooms with Names, Dimensions, Amenities, etc.)
Businesses can have more than one type (Restaurant, Venu)

What I'd like to do is be able to show different sets of inputs based on what categories are selected.

Check Restaurant

Reveal a list of Restaurant types, because that is relevant only to restaurants.

Check Venue

Reveal a table field type so you can enter a list of room names with corresponding features and amenities.

Is there a way in Craft, or is there a plugin that lets you run logic based on inputs to show or hide other inputs?

Check out the Reasons plugin... sounds like exactly what you need:

  https://github.com/mmikkel/Reasons-Craft/


Making custom changes to CP language I want to change a few words in the CP (Craft 3). What's the best way to do it, without being overwritten by a Craft update if possible...?
I was thinking about creating my own language file, but can't find the complete method to do so, and it might still be affected by an update? Any ideas?

Just create translations/en/app.php directory of your Craft installation with the following content (replace en with the desired language code):
<?php return [
    'Settings' => ' Params',
];

Craft updates won't touch it.


French local returns "en"? I'm trying to check my craft locale to offer language switching but it seems that my french locale returns the "en" value???

When I run the following:
{% if craft.locale == 'fr' %}

I instead get the contents of:
{% if craft.locale == 'en' %}

Is anyone experiencing this? I don't see any code that could be messing with the code.

Note: the site url outputs just fine: mysite.dev/fr/ BUT if I print {{ craft.locale }} I get "en".

You probably forgot to set the CRAFT_LOCALE constant for your French site in /fr/index.php, to tell Craft which locale's content to serve.


Get Entries From Any Section Matching a URL segment I have 2 issues that I need help with:

I want to load ENTRIES from any section where the first URL segment of the entry matches jobs.
I am using the code below to load any SECTION where the first URL segment matches jobs.  This code works to load the sections. I'm just wondering if there's a more efficient way to write this to load the sections.  This is separate from loading the entries.  I need to do both.

{% set allSections = craft.sections.getAllSections() %}

{% for section in allSections %}

{% set sectionURL = section.getUrlFormat()|split('/')[0] %}

{% if sectionURL == "jobs" %}
    {{ section.name }}
{% endif %}

{% endfor %}

To check if the word jobs is in the sectionUrl you can use twig's matches to create a regular expression that looks for jobs

{% set allSections = craft.sections.getAllSections() %}
{% for section in allSections %}
    {% set sectionURL = section.getUrlFormat()|split('/')[0] %}

    {% if sectionURL matches "/jobs/" %}
        {{ section.name }}
    {% endif %}

{% endfor %}


How to use Class Reference Classes within the Craft framework for plugin development I am attempting to lean how to write a plugin but am having trouble knowing how to work with the Class Reference documentation. I understand all of the theory and how object oriented programs work. But I have never actually worked on a real world problem. I have only worked on small programs to learn the concepts.

I am overwhelmed by the Class Reference and don't know best practices for attacking a new project and using the Class Reference documentation. I feel overwhelmed and stuck, and so my question is can an experienced developer or two share some guidance as to their methodology for working with a framework in the real world?

The plugin itself is conceptually simple. I'm working on developing a application similar to tinyurl.com.  I need to store data in a database table and then read it back. I also then need to then figure out how to do a redirect.

My main goal is to get the general guidance on how to approach any new project with regard to how to start. Any guidance on the specific problem is also appreciated.

You may already be aware of this, but the Class Reference is a complete breakdown of the Craft core. Everything that exists within the craft/app folder is documented here.

Craft is built upon the Yii framework. If you dig deep enough, many roads lead back to Yii queries. Fortunately, you'll rarely have to dig that deep! Craft has abstracted away much of the raw Yii commands into all of its Base classes.

Continuing from there, pretty much everything else that happens in Craft is layered upon the Base classes. You'll notice that most of the common components (Services, Controllers, Records, etc) contain a Base class, and all other classes are extended from there. In general, you can think of the Craft core as being "one big plugin"... In fact, when Craft 3 is released, this will be even more true.

It's important to note that your plugin won't need all of these components. Many plugins require only a few of these components to meet their needs. In your case, you may only need a Service, a Controller, a Record, a Model, and a Variable.

Beyond that, I'll skip any recommendations for your specific plugin project. My intention was only to respond to the general purpose of your question... I'd highly recommend opening a separate question with specific points about what you are setting out to accomplish.


Return element criteria model from attribute of a model In one of my Plugin's CP templates I am using a element select field to grab elements from a custom element type.  This field saves an array of element ids to a specific record's attribute called "location".  How do you return an element criteria model instead of the array of ids when the model attribute is called via twig?

// Model
protected function defineAttributes()
{
    return array_merge(parent::defineAttributes(), array(
        'location'          => Attributetype::Mixed,
        'specificLocation'  => AttributeType::String,
        'registration'      => AttributeType::Mixed,
    ));
}

// Front end template
{{ craft.pluginname.variable.location }}

If I'm following you correctly, seems like you could override your Model's getAttribute method to do something like this completely untested code:

public function getAttribute($name, $flattenValue = false)
{
    if ($name == 'location' && $flattenValue != false)
    {
        $criteria = craft()->elements->getCriteria('MyPlugin_MyElementType');
        $criteria->location = parent::getAttribute($name, $flattenValue);
        return $criteria;
    }

    return parent::getAttribute($name, $flattenValue);
}

If I'm not following you correctly, then that was pointless.


Save field inputs upon submission of front end form for reuse in new form? Is there a straightforward way of saving the input of two form fields when a form is submitted from the front end and reusing it in another form?

One field is a select2 field (Users) which can contain multiple users and the other is a number field (Log ID).

The current workflow is that a user fills out a form and it's submitted to the database.  It's very likely that he will need to fill out additional forms immediately afterwards and two of the fields he inputed (Users and Log ID Number) in the first form are the same in the second form.

The workflow that came to mind was whether after first form submission, I could append the Users and Log ID into the url query string and then have them available to prepopulate in the additional forms.  Perhaps on a successful form submission page, I could have a button to allow the user to submit another form and if clicked, it goes to the new form page and grabs the url query string values and enters the info in the two fields.

Totally open to other ways of seeing this too so feel free to throw your thoughts out there.

Thanks!
Lori

I don't know if we can compare the problem I usually have but here is my way.

Whenever I build a website where users can login and save "entries" they also need to stay connected to it off course.
I make sure the title of the new made entry got the users ID in it. So if someone makes a new entry they go to a succes page after the form is submitted. This success page is actually the entry they created. The moment they land on that page the "second" form will be automatically filled in with the details I need and then save/update whatever needs to be updated (most of the times for me that would be saving the entry to a user profile). After the second form submit's I redirect them to the page I want.

This would include some javascript.


Intercepting Sprout Forms "onSaveEntry" Event In Craft 3 Plugin I've built lots of Craft 2 plugins that catch Sprout Forms submissions and integrate with external services (CRM's etc). It was easy, you'd make a plugin and catch the event going:

craft()->on('sproutForms.onSaveEntry', function(SproutForms_OnSaveEntryEvent $event) {
    // Hand submission off to your service to do some rad stuff.
});

But in Craft 3, that events functionality appears to be more complicated. All the Events & Hooks area in the Sprout Documentation just show "Example needed." in all the places where code samples would usually be. The Craft 3 plugin docs on events show a new system for registering and intercepting events - but my coffee deficient mind is struggling to figure out how to map that to Craft3/Sprout Forms 3.0.0-beta.17.

Has anyone built a Craft 3 plugin that works with Sprout Forms Beta yet? I'm even struggling to find examples of any event integration in plugins at the moment.

Halp!!!

I've updated the Sprout docs with examples of Craft 3 events and hooks.

In your case, the Form Entry Element extends the craft\base\Element class and also supports the same after the base element save event: EVENT_AFTER_SAVE. In your primary plugin class init method:

use barrelstrength\sproutforms\elements\Entry;
use yii\base\Event;
use Craft;

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

    Event::on(Entry::class, Entry::EVENT_AFTER_SAVE, function(Event $event) {
        if (Craft::$app->request->isSiteRequest)
        {
            // A Form Entry Element has been saved from a Front-end Form Submission
            Craft::dd($event->sender);
        }

        if (Craft::$app->request->isCpRequest)
        {
            // A Form Entry Element has been updated from the Control Panel

            Craft::dd($event->sender);
        }
    });
}

You can access the specific Form Entry Element being submitted via the $event->sender property.


Formatting Headers, Quotes, Titles I've just updated to 2.5 and am now not able to see or find the text styling option in a text box. We use the formatting option across our site for different headers, quotes, etc. Am I missing something or is the feature gone?

If your Redactor config included a "formatting" value in the "buttons" array, you need to rename that to "format".

https://craftcms.com/help/redactor-ii-configs


How do you customize what value a Custom FieldType returns to a template Is it possible to control what gets output in the template a custom fieldtype?

For example im working on a eventbrite plugin and it saves the id in the database but I want the field in the template to return a fully formatted register button.

Right now im doing this with a craft variable that i'm passing the id and returns the html for the button into but feels like there might be a simpler way?

Related to that right now i have to add | raw to the variable output

so its

{{ craft.eventBrite.registerButton(entry.eventbriteId) | raw }}

is there a way to prevent the escaping of whats being returned without the extra filter in the template?

Run your HTML string through getRaw before sending it back to the template...

return TemplateHelper::getRaw($output);

This will basically "pre-raw" your HTML string.


search parameter passed to include I have a template where I would like to pass a search parameter to a craft.entries.section in an included template. The current main template has this:

{% include "_includes/testimonial" with
  { type: "agency" }
  %}

Then in the include I have this code where entry.clientsOrAgency is a dropdown field and I want it to only show results of the "type" passed in the parent template.

{# get one random testimonial entry #}
{% set testimonial = craft.entries.section('testimonials').search(entry.clientsOrAgency,type).order('RAND()').limit(1) %}

{% for quotes in testimonial %}
<div class="testimonial">

  {# matrix field is 'testimonial' - find different quote types #}
  {% for quote in quotes.testimonial %}
    more code here
  {% endfor %} {# quotes.testimonial #}

</div><!--testimonial-->
{% endfor %}{# quote in testimonial #}

The above code results in a template error Undefined index: query

Not sure how to resolve this.

Your syntax is a bit off – the search() parameter doesn't accept multiple parameters, only a search query (e.g. .search('body:foobar')) or an object containing the search query plus search term options. In your case, you're actually passing an object (.search(entry.clientsOrAgency)), in which case Craft will look for a query parameter on that object (the second parameter is just ignored). Hence your error.

That being said, here's what you probably want:

{% set testimonial = craft.entries.section('testimonials').search('clientsOrAgency:'~type).order('RAND()').limit(1) %}

The above will search for entries in the testimonials section, which has the value equal to type in each clientsOrAgency field.

However – unless you need (which can be enabled as a default for all searching in Craft, or per-search using search term options mentioned above) for the clientsOrAgency field, I don't actually think using search() is the appropriate approach here. The following would be easier and probably more performant:

{% set testimonial = craft.entries.section('testimonials').clientsOrAgency(type).order('RAND()').limit(1) %}

Also, you should probably add .first() to your craft.entries query, in order to only pull a single entry:

{% set testimonial = craft.entries.section('testimonials').clientsOrAgency(type).order('RAND()').limit(1).first() %}

{% if testimonial %}
    ...
{% endif %}


Asset Filename Query using Product SKU I'm moving an e-commerce site over from EE. Many of the products have a "product image". Many do not, but we have an assets directory full of images that match their SKUs.

When listing the products by category, I want to call images in the following order:
1. If there's a product image, crop and display the product image.
2. Else if there's an asset filename that matches the product SKU, crop and display that asset.
3. Else, display a stock image that says no image available.

I'm running in to a problem with step 2. I can display the product SKU in lowercase in the template, but I don't know how to make the asset query using the product SKU.

How can I get the results of productPic in to the assets query below it?

{% for rental in rentals %}

        {# If there's a product image, crop and display the product image.#}
        {% if rental.productImage|length %}
        {% set image = rental.productImage.one() %}

        {# Elseif there's an asset filename that matches the product SKU, crop and display that asset. Using rental.title temporarily to trigger this conditional. #}
        {% elseif rental.title|length %}
        {% set variant = rental.defaultVariant %}
        {% set productPic = variant.sku|lower %}
        {{ productPic }}
        {% set image = craft.assets.filename('').one() %}

        {# Else, display a stock image that says no image available. #}
        {% else %}
        {% set image = craft.assets.id(9225).one() %}

        {% endif %}

    {{ rental.title }}

{% endfor %}

I'm basing this response on the incomplete statement {% set image = craft.assets.filename('').one() %}.

To get an asset named the same as the SKU of a Product's default Variant, try this:

{% set exampleImage = craft.assets({
    filename: "#{myProduct.defaultVariant.sku | lower}.*"
}).one() %}

This does a couple things:

Collapses the transformation of a product into a search string using Twig's string interpolation, and the filter you'd applied;
Appends .* to match all extensions (optional, but recommended, in the event you have some PNG, JPG, and JPEG images in your library);
Executes the query and returns a single Asset Element or null.

Always check you have results before attempting to access properties of your image:

{% if exampleImage %}

{% endif %}

I think the original problem you were encountering was that (by default) the filename query parameter matches strictly, meaning that your SKU would need to be the complete filename in order to be returned. You can view the fuzzy-matching syntax/options in the Asset Query documentation.

With respect to the overall structure of the code, I'd recommend an approach like this:

{# First, look for an attached image: #}

{% set image = myProduct.productImage.one() %}

{# If there wasn't one, try looking in the Asset library: #}

{% if not image %}
    {% set image = craft.assets({
        filename: "#{myProduct.defaultVariant.sku | lower}.*"
    }).one() %}
{% endif %}

{# We might still be missing an image. If so, fall back to fetching a specific one: #}

{% if not image %}
    {% set image = craft.assets({
        id: 9225
    }).one() %}
{% endif %}

{# Ok, now we're guaranteed to have one of the above images—we can safely use `image` the same, regardless of where it came from: #}


Barebones LEMP + Craft CMS walkthrough No fancy deployment, version control etc etc. Just a cut and dry walkthrough on how to get Craft CMS up and running on a LEMP stack, does it exist? I'm fairly new to craft but have had no problem with the more documented LAMP stack but there seems to be a lack of LEMP & specifically nginx directives relating to craft. Any help or advice would be greatly appreciated.

Here is one: https://medium.com/good-dog/deploying-craft-cms-to-amazon-ec2-running-the-lemp-stack-using-mina-e2ad955138fa#.54s4y29co

Disclaimer: I work for the company that published this.


How can I test if a request returns a 404? In my 404 template I am extending a layout template. Inside that layout template I want to hide a section use an {% if craft.request... == 404 %} test. Any ideas on how I can accomplish this?

That solution is viable. You can just test to see if the entry or the template matches your 404 template/entry. If you routed everything correctly to display a 404 in case of error, you should be fine.


Create a "hidden" page within Structure Is it possible to create a hidden page within a Structure similar to how the Structure addon in EE does? It is still available at the url, but is excluded from the navigation.

I know there are several ways I could handle this, 3rd level nav, possible custom field (lightswitch), additional structure for hidden items, etc. These just don't sound like perfect solutions. Any other ideas?

Well, a custom field actually does sound like the perfect solution. It's easy and consistent to check on all outputs and areas (sitemap/menu's/other navigations).


Title field character length Is it possible to limit the title field in an entry?  As with other fields I can adjust so that it only takes a certain amount of characters.

You can create a custom validation at the EVENT_BEFORE_SAVE event

Event::on(Entry::class,
    Entry::EVENT_BEFORE_SAVE,
    function(ModelEvent $event){
        /** @var Entry $entry */
        $entry = $event->sender;
        // you can check for the section and the type

        $model = DynamicModel::validateData(['title' => $entry->title], [
            [['title'], 'string', 'max' => 2, 'message'=>'{attribute} should not be longer than 2 characters']
        ]);
        if($model->hasErrors()){
            $entry->addErrors($model->getErrors());
            $event->isValid = false;
        }
});

You can leave remove the message attribute if you don't want to use a custom error message, I just wanted to provide a full example how to validate data in Yii2. That way you can define whatever rule you want


Is it possible to determine if a script is running within a task? I have a chunk of PHP code which should not be run if the script is being executed from a task.

We already have these methods, which are similar to what I'm looking for:

craft()->isConsole() - Whether the script is running in the console.
craft()->request->isCpRequest() - Whether the script is running in the CP.

Is there a way to tell if the script is running inside of a task?

(Since my research has turned up nothing so far, I opened a related feature request...)

TasksService->getRunningTask() will tell you if a task is currently running. However, it doesn't tell you whether a particular chunk of code is being executed by that Task or by some other function.

The most straightforward solution I can think of would be to write yourself a little helper method to check whether the call stack includes a Task class:

static function inTask()
{
   foreach(debug_backtrace() as $caller)
   {
      if (substr($caller['file'], -8) === 'Task.php') return true;
   }
   return false;
}

Add that to your plugin class, and then you can call it anywhere you need:

if (MyPlugin::inTask()) ...


How to include and use native imagemagick on server in Craft? Craft v2.6.x

I want to write a plugin to grab thumbnails of PDFs.

I have my stand alone php code with imagemagick on server working like this:

$im = new Imagick();
$pdf = 'assets/documents/resources/after-release-impact-seafarers.pdf';

$im->setResolution(300,300);
//$im->setCompressionQuality(95);
//$im->scaleImage(200,0);
$im->readimage($pdf . '[0]');
$im->setImageFormat('jpeg');
//$im->resizeImage( 640, 905, imagick::FILTER_POINT, 1 );
//$im->resizeImage( 400, 565, imagick::FILTER_POINT, 1 );
$im->resizeImage( 180, 232, imagick::FILTER_POINT, 1 );

$im->writeImage('1a2w12thumb.jpg');
$im->clear();
$im->destroy();

However, how can I load imagemagick - which works on the server in my PDF thumbnail plugin class function?
I have tried:

    $im = new \Imagick();

    $im->setResolution(300,300);
    $im->readimage($pdfAsset . '[0]');
    $im->setImageFormat('jpeg');
    $im->resizeImage( 640, 905, imagick::FILTER_POINT, 1 );
    $im->writeImage($pdfAsset->writepath.$pdfAsset->filename . '.jpg');
    $im->clear();
    $im->destroy();

But none of the functions for imagemagick work:
Eg. error i get is Class 'Craft\imagick' not found

Is this a namespace issue with the imagine library? (I sound like I know what I am talking about but I am not sure I do!)

How to include/ use native imagemagick on server in Craft?

If you want to work with PECL imagick, which is the PHP wrapper for the ImageMagick library, then this should work:

$im = new \Imagick();

It's not namespaced, so it exists in the global namespace, which is what the \ does for you.


How can I configure multi-site base URLs where the subdomains are static but the domain name is dynamic? For example, let's say I have two sites: abc.example.com and xyz.example.com but I want to also host test versions of those sites at example-test.com.
It'd be nice if I could set the baseURLs to http://abc.$DOMAIN and http://xyz.$DOMAIN and then set the env var DOMAIN on the server (or something similar), but Craft currently only supports setting base URL to an env var if that is the entirety of what it is set to.
I'm not interested in creating an env var per subdomain.
Any ideas?

You could achieve this using Aliases.
In your .env, you could set DEFAULT_DOMAIN="yourdomain.com" then in your config/general.php you would do:
'aliases' => [
    'siteAbc' => 'http://abc.' . getenv('DEFAULT_DOMAIN'),
    'siteXyz' => 'http://xyz.' . getenv('DEFAULT_DOMAIN')
],

With this in place, you will be able to use @siteAbc and @siteXyz to set your site URL as well as @siteAbc/images for your assets Base URL for example...
Note that all naming convention is up to you, of course...


Getting checkbox options for a new entry, without having an entry How would I get a list of all the checkbox options associated with a specific field, without having an entry to loop over? I'm using the same form for creating new entries and editing existing ones. Been using {{ entry.fieldValue | default( ) }} for almost everything else.

{% if entry is defined and entry.id is not empty %}
    {% for option in entry.myFieldOptions.options %}
        <div class="checkbox">
            {% set checked = false %}

            {% if option.selected %}
                {% set checked = true %}
            {% endif %}

            {% if not checked %}
                <input type="hidden" name="fields[myFieldOptions][]" value="">
            {% endif %}

            <input type="checkbox" value="{{ option.value }}" name="fields[myFieldOptions][]" {% if option.selected %} checked="checked"{% endif %}>{{ option.label }}
        </div>
    {% endfor %}
{% else %}
    //hardcoded values
    //is there a way to reference available checkbox options directly?
{% endif %}

You can pull the field directly using craft.fields:

{% set myFieldOptions = craft.fields.getFieldbyHandle('myFieldOptions') %}

The options will be available under the field's settings.options property. Each option will have attributes for value and label:

{% for option in myFieldOptions.settings.options %}
    {{ option.label }} {{ option.value }}
{% endfor %}


How do you sort elements queried from multiple channels? This is how I query elements from multiple channels:

{% set allEntries = craft.entries.section(['publication','text', 'exhibition']).limit(null) %}

I now want to sort all these entries by a custom date field. If all channels had the same date field, I would just append order('releaseDate desc') to the query.

But as I have chosen to set up individual date fields (i.e. publicationReleaseDate, exhibitionOpeningDate) I cannot figure out how to join and sort them.

Of course I could just use the same field in all channels, but then I can't have individual field names and instructions per channel.

The order param sets the ORDER BY part of the MySQL query. You can also pass MySQL functions in it.

In your case GREATEST() should do the job:

{% set allEntries = craft.entries
    .section(['publication','text', 'exhibition'])
    .order('GREATEST(releaseDate, publicationReleaseDate, exhibitionOpeningDate) desc')
    .limit(null) %}


Looping through returns nothing after using dynamic routes to get the entry type and category I'll explain a bit of the structure of the content and then proceed to the issue.

So i have a website with a shop in it with the url mysite.com/shop/,
it is an channel section, and its template is located at craft/templates/shop/index.html.

The shop is divided in to 2 categories - "new", and "used",
the url for each is mysite.com/shop/(used or new), and its template is located at craft/templates/shop/category.html.

The section(channel) shop that is mentioned above also has multiple entry types, for example "televisions", "consoles", "computers"... and each one has a required category field to chose one of the above(new or used), and the url for those entries is 'shop/{condition.first().slug}/{type}/{slug}'
(the condition field is the category).

Now to what i'm trying to do, and whats the issue.
I want the user to be able to filter through entry types within the category template. what i mean is that te used could click "show only tv's"
and a url with the new filter will load but with the same template, so the url would look like that:
mysite.com/shop/used/television/

To accomplish that i've made a new dynamic route by adding the nex line to my routes.php:
'shop/(?P<segmentCategory>(new|used))/(?P<segmentEntryType>[a-z]+)' => 'shop/category',

And the template goes like this(the twig part only):

{% if segmentCategory is defined %}
    {% set category = craft.categories.slug(segmentCategory).first() %}
    {% set entries = craft.entries({
        type: segmentEntryType,
        relatedTo: ['and',
            { sourceElement: category },
            { targetElement: craft.entries.type(segmentEntryType).status(null).first }
        ]
    }) %}
    {% if not entries %}
        {% exit 404 %}
    {% endif %}
{% else %}
    {% set entries = craft.entries.relatedTo(category) %}
{% endif %}

{% for entry in entries %}
    {{ entry.title }}
{% else %}
    There are no entries matching you criteria right no, please try again in a few days.
{% endfor %}

I'm having two issues with this code.

First: {% if not entries %} never executes, even if i enter complete nonsense in the url.
Second: the array entries is never outputs anything...

Thanks ahead!

{% if not entries %} never executes, even if i enter complete nonsense in the url.

You’re not ensuring that segmentCategory is a valid category slug anywhere. If it’s not, then category will get set to null, which will basically prevent it from affecting the following relatedTo param.

So right after grabbing the category you should make sure it exists;

{% set category = craft.categories.slug(segmentCategory).first() %}
{% if not category %}
  {% exit 404 %}
{% endif %}

  the array entries is never outputs anything

I think this is because your relatedTo parameter isn’t set up correctly. If the used/new categories are being assigned to the entries via a Categories field on the entry, then the category should be set to the targetElement property, not sourceElement, since the category is the target element of the relation. And you can just get rid of the current targetElement stuff, which should have been sourceElement, but is redundant and doesn’t need to be specified anyway.

{% set entries = craft.entries({
    type: segmentEntryType,
    relatedTo: { targetElement: category }
}) %}

  Ok, now i get the posts, but if i pass an invalid string to the segmentEntryType the template still loads.

This conditional:

{% if not entries %}

should be:

{% if not entries|length %}

(At this point in your template, entries will be a defined ElementCriteriaModel regardless of whether it matches any entries. Including the length filter in your conditional will force it to execute the DB query and return the actual results.)


Templating data in HTML I have an Matrix field and I want to extract data in the following HTML structure:

text1

text2

text3

text4

text5

text6

and this is my twig code for retrieving data from craft:

{% for entry in entries %}
  {% if loop.index is divisible by(3) %}

text4

text5

text6

{% else %}

text4

text5

text6

{% endif %}
{% endfor %}

I want to output multiple browse with free divs
I am new to Craft and I will appreciate any help, thanks!

Not sure if you really wanted dynamic variable names like imgurl1 or not, but something like this?

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

text{{loopIndex}}

    {% if loopIndex is divisible by(3) %}
        {% if not loop.last %}

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


How to prepend user input data to a filename uploaded through Sprout Forms I have a contact form where users have to fill in a name field and upload a file.  I want to add the name the user filled in to the beginning of the filename, eg: firstname-lastname_filename.pdf.  I am using Sprout Forms for Craft 3, both the most up to date versions.
Is this something I can do with original Sprout Forms functionality, or will I have to write a custom module or plugin to inject this code?  Essentially, what I understand is I will have to find the code in Sprout Forms where the file is uploaded, and inject the code to add the special user submitted name data.

Sprout forms has hooks you can latch on to in your own custom module/plugin, so when a form is saved you can grab the asset and re-name at that point.


Timestamp of last run from Feed Me-feed I have multiple feeds being run via cronjobs, and would like to display front end "Last updated: 15:38 18. June"

Does anyone know if its possible to get the timestamp of the last import from a specific Feed Me feed?

I've found the following from the docs, but it seems to be pointed towards running a feed. I just want to get data out of the log from a feed.

{% set params = {
    url: 'http://path.to/feed/',
    type: 'xml',
    element: 'entry',
    cache: 60,
} %}

{% set feed = craft.feedme.feed(params) %}

The information that shows up on in the admin/feed-me/logs portion of your Control Panel is pulled directly from the Feed Me logs on the filesystem at storage/logs/feedme.log.

So you'd need to write a little plugin that parsed those files and exposed the data you want back to the template to display it.


Craft 2.2 with enabled enableCsrfProtection: Failed to load resource: the server responded with a status of 400 (Bad Request) Since the update to version 2.2 I can't upload assets.

I get this error message in the console:

Failed to load resource: the server responded with a status of 400 (Bad Request)

And the upload stops:

Any idea why?

I can confirm this is a bug on Craft 2.2.2579 when CSRF protection is enabled.  Will get a fix out for it shortly and update this answer when it's done.

Update:

Fixed in Craft 2.2.2582.


Sprout SEO best practice - single or multiple field types? I think I know the answer for this (multiple) but I just wanted to see how others are doing it?

Right now I have a single default meta field type that I add to most of my sections. At this stage I've got the advanced 'Meta Details' turned off but we're starting to need to make per section tweaks and I'm looking at enabling this.

Given we want finite control (and better sectional specific fall backs if the meta information isn't supplied) I'm now realising that most people probably have a meta field for each section?

If I do migrate from a single to multiple (~30 sections atm) there's not a simple way to migrate the existing meta data is there?

tldr; Use as many Element Metadata fields as you need unique mappings between your Elements and your metadata. You can replace an existing Element Metadata field with a new one without losing data, but it will depend on the field settings of the old and new field.

A single Element Metadata field as a starting point

A single Element Metadata field across all sections is a good place to start. It reduces project overhead for getting things setup and provides a starting point with more comprehensive metadata than most sites. I typically recommend creating two custom fields: Summary and Feature Image and then mapping the single Element Metadata field to those common fields: Title, Summary, and Feature Image across all sections.

As you describe, in some cases you begin to need more specific metadata. This is a good signal for when to start considering multiple Element Metadata fields. Often, a section may have custom fields that are better suited for its metadata, and creating an Element Metadata field specific to that section will give you the flexibility to customize that sections metadata in a unique way.

Updating Element Metadata fields

If you're transitioning from an existing Element Metadata field to a new one, it's good to think about it like a migration and any SEO implications that may be affected if your metadata changes. Depending on how you set things up initially, and on what you are trying to achieve, there are a few considerations.

Dynamic Metadata

The easiest way to manage metadata is to have it dynamically generated from other content fields already present in your element field layout. If you take this approach, admins are not manually entering any metadata and all metadata is being generated based on the pattern that you set it up with.

If you update the patterns of your dynamic metadata in the Element Metadata field or add a new Element Metadata field to a channel to replace an old one, you don't need to migrate any metadata because the new field will generate the metadata dynamically for you. When you change the settings in an Element Metadata field or resave a Field Layout, Sprout SEO triggers a ResaveElements task (just like Craft does when you change a URL Format in your Section settings) and resaves all Elements that are related to that field which also resaves all the metadata based on the pattern you have in the field settings.

While you don't have to take any action on your website, note that in this scenario, if you change the metadata pattern, you are potentially changing the metadata on all of your pages. Make sure the changes are what you want and test and monitor those changes accordingly for your needs.

Custom Metadata

If you've enabled admins to edit metadata directly via Editable Meta Fields or the Meta Details overrides, the data should persist if you change to a new Element Metadata field. Sprout SEO only supports one Element Metadata field per Field Layout. When you update a field layout and replace an old Element Metadata field with a new one, as far as your Element is concerned, the only thing that changed is the Element Metadata field settings.

Again, be sure to test any changes you make and confirm the data is still there. It is possible to change the settings in a way that would overwrite some metadata when elements are resaved. But, if you keep the same custom metadata Editable Fields or Meta Details fields enabled, the existing data should persist.