SEOmatic: Change type of mainEntity With SEOmatic I want to be able to dynamically change the type of my mainEntity, which defaults to "Webpage" and in some cases I want to change it to "Event"
In an older project I did this:
{% do seomatic.jsonLd.get('mainEntityOfPage').type('Event') %}

But if I dump the mainEntity again, nothing has changed:
{% dd seomatic.jsonLd.get('mainEntityOfPage') %}

It's still a nystudio107\seomatic\models\jsonld\WebPage#1
How can I achieve this?
I'm using Craft 3.4.30 with Seomatic 3.3.35

So you can't just change the type of the mainEntityOfPage because there's a unique PHP class for each schema.org type.
What I would typically recommend here is that you set up the mappings via Content SEO (which lets you set up a different mainEntityOfPage per entry type) or you use the SEO Settings field to allow for per-entry changing of the mainEntityOfPage.
But if you really want to do it dynamically via Twig, you can. You just need to create a new object.
{% do seomatic.jsonLd.create({
    'key': 'mainEntityOfPage',
    'type': 'Whatever',
{# fill in other properties here #}
}) %}


Creating a editable table with Element Select in column First of all, I'm starting in Craft in general so I'm having a hard time with things that might be basic.

I want to create a editable table with a Element Select in a column. Like:

I already have the possibility to add custom fields, but I don't now how to set up the template.

{{ forms.editableTable({
    id: 'timetable',
    name: 'timetable',
    required: false,
    cols: {
        name: {
            heading: "Name" |t,
            type: "select" |t,
            options: {
                'area-x' : 'Area X',
                'area-y' : 'Area Y',
                'area-z' : 'Area Z',
            }
        },
        artists: {
            heading: "Artists" |t,
            type: "elementSelect" |t,
        }
    },
    rows: ///
}) }}

But of course that doesn't work.

Can anyone light up the way?

For my specific case, Super Table was the answer.

You can also check Neo


How to redirect to Coming Soon template I want to redirect http://example.com to coming-soon.html template, but not index.html.

Possible to do it in route settings?

If you are trying to cover the site from the public while working on it live, i personally would name my coming soon template file 503.html

Then in the General Settings section of the control panel, switch System Status off.

That way so long as you are logged in, you can access the site as normal but anyone else visiting your site will see the contents of the 503.html template.


Hide (or disable) an entry field in CP depending on user group permission? So I am trying to hide (or disable) a field in the "Edit Entry" view in the CP.

I know how to test a user group :
{% if currentUser.isInGroup('groupHandle') %}

But I cannot find a hook in Craft Doc to change the rendering of my field ?
Perhaps with getInputHtml()? But I dont understand exactly how...

OK so here is my solution :
1/ define a custom permission for user groups

public function registerUserPermissions()
{
    return array(
        'updateTopNews' => array('label' => Craft::t('Update Top News')),
    );
}

2/ simply add css to hide the field when user has not the permission in my plugin init function

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

    $user = craft()->userSession->getUser();
    if ( craft()->request->isCpRequest() && $user ) {

        if ( !$user->can('updateTopNews') ) {
            craft()->templates->includeCss('#fields-topNews-field { display: none; }');
        }
    }


Template Variable Already in Use? I am brand new to craft and have loved it so far.  Only area that I'm having a hard time understanding is why I cannot use my template variables in my templates.

I am routing news/ to an action which then uses the renderTemplate() method to do just that...render the template.  The result is sent to the browser but it is accompanied by the following php error:

Fatal error: Cannot declare class Craft\WassermanNewsVaraible, because the name
is already in use in /usr/share/nginx/craft/plugins/myPlugin/variables/MyPluginVariable.php on line 5

So that tells me that the class is obviously already declared somewhere.  If so how can I access it?  I am currently trying to access it as the documentation describes and is shown below:

{% for item in craft.myPlugin.myMethod() %}
  <div>
   Test
  </div>
{% endfor %}

Here is my template variable class which is in myPlugin/variables/

namespace Craft;

class MyPluginVaraible
{
    public function myMethod(){
        craft()->myPlugin->myMethod(); //which is in the service
    }
}

Is there a difference between how templates are rendered via controllers as opposed to the regular behavior?  I saw that the method had a second parameter however I still could not insatiate my template variables to pass that way as it was still already declared somewhere.

I've been banging away at this one for a while.  Any help or insight would be much appreciated.

MyPluginVaraible Note the spelling of the highlighted word...


how to create Super Table field programmatically i am trying to create a super table field programmatically.
this is the code i tried.

i see super table field in field list but i can see fields inside of super table.

how can i do this?

    //create super table field itself
    $superTable = new SuperTableField([
        'name' => 'supertablefield',
        'handle' => 'supertablefield',
        'groupId' => 1
    ]);
    Craft::$app->getFields()->saveField($superTable);
    //field inside super table
    $field = new \craft\fields\PlainText([
        "name" => 'textfield',
        "handle" => 'textfield',
        "translationMethod" => "site",
        "multiline" => 0,
    ]);
   //create and set block type
    $blockModel = new SuperTableBlockTypeModel();
    $blockModel->fieldId = $superTable->id;
    $blockModel->uid = StringHelper::UUID();
    $blockModel->setFields([$field]);

    $superTable->setBlockTypes([$blockModel]);
    SuperTable::$plugin->service->saveBlockType($blockModel);

Not sure if this is the answer without playing, but try saving the plain text field before adding it to the super table:

    // Create the super table field

    $superTable = new SuperTableField([
        'name' => 'supertablefield',
        'handle' => 'supertablefield',
        'groupId' => 1
    ]);

    Craft::$app->getFields()->saveField($superTable);

    // Create plain text field

    $field = new \craft\fields\PlainText([
        "name" => 'textfield',
        "handle" => 'textfield',
        "translationMethod" => "site",
        "multiline" => 0,
    ]);

    // Save the plain text field

    Craft::$app->getFields()->saveField($field);

    // Retrieve the plain text field

    $plainTextField = Craft::$app->fields->getFieldByHandle("textfield")

    // Create and set the block

    $blockModel = new SuperTableBlockTypeModel();
    $blockModel->fieldId = $superTable->id;
    $blockModel->uid = StringHelper::UUID();
    $blockModel->setFields([$plainTextField]);
    $superTable->setBlockTypes([$blockModel]);
    SuperTable::$plugin->service->saveBlockType($blockModel);


How to prevent non-image files being uploaded through frontend form? Is this possible? At the point of upload, the entry field isn't checked so anything can be uploaded, which is a bit worrying.

Then again, if it's an Amazon S3 bucket, does it even matter? It won't be sitting on the server.

There is a checkbox when creating/editing the field labeled "Restrict allowed file types?" Checking it will reveal file type options.

Source: https://craftcms.com/docs/assets-fields


Get Asset Image File Name I'm trying to get the actual file name of each images when looping through the image assets folder, which looks like:

{% for image in craft.assets.kind('image').folderId('1').order('filename') %}

{% endfor %}

I need to be able to include the filename of the image as a data attribute in the  tag. I tried all sorts of variations of {{ image.fileName }} but have had no luck. Can't find a solution searching here. Does anyone know how? Better yet - is there a documentation somewhere showing all the available twig attributes for assets/images?

image.filename should work unless I'm missing something. Note that it is case-sensitive.

The documentation on AssetFileModel can be found here:
http://buildwithcraft.com/docs/templating/assetfilemodel


Commerce: Show quantity discounts starting point

I have the following offer with quantity discounts for a series of my products:

Buy 1 item and get $5 off per item
Buy 2 items and get $10 off per item
Buy 3 items and get $15 off per item

I set these discount rules in my control panel under "commerce" > "promotions".

product template

Now in my product template, I would like to be able to output (for each quantity level):

the normal (non-discounted) price
the discounted price
savings in terms of $
savings in terms of %

example

For example it would then say on the product page (output):

  "If you buy 2 items, you only pay $[discount price for 2 items]
  instead of $[normal price] per item. So your total today is only
  $[2 x discount price for 2 items] insted of $[2 x normal price].
  You therefore save $[(2 x normal price)-(2 x discount price for 2
  items)]. That's a discount of […]%."

The same goes for the discount offer of ordering 1 item or 3 items.

How can I accomplish this with all the discounts and math operations involved?

What have you tried so far?

The documentation seems to be missing, but looking at /craft/plugins/commerce/models/Commerce_DiscountModel.php you can find the properties purchaseQty and perItemDiscount that you need for the calculations.

{% for prod in product.variants %}
   {% for discount in craft.commerce.discounts %}
      {% set totalPrice = (discount.purchaseQty * prod.price) %}
      {% set totalDiscountPrice = (discount.purchaseQty * (prod.price + discount.perItemDiscount)) %}
      {% set totalDiscount = (totalPrice-totalDiscountPrice) %}
      {% set totalDiscountPercent = (totalDiscount/totalPrice)*100 %}

If you buy {{ discount.purchaseQty }} items, you only pay {{ totalDiscountPrice|currency(cart.currency) }} instead of {{ prod.price|currency(cart.currency) }} per item. So your total today is only {{ totalDiscountPrice|currency(cart.currency) }} insted of {{ totalPrice|currency(cart.currency) }}. You therefore save {{ totalDiscount|currency(cart.currency) }}. That's a discount of {{ totalDiscountPercent|round }}%.

   {% endfor %}
{% endfor %}

This will show all of the discounts for all of the products. You will need to modify it slightly if you have specified the discount for a specific product. You also need to check if the discount is enabled or not using discount.enabled


How do you create pagination links related to entries within a Matrix Field in a single entry? I have combed through similar questions, although my pagination links are not performing properly.

I would like to add pagination links to entries within a channel. And I would like for the pagination order to be pulled from an Entries field within a Matrix located within a Single entry.

So far I have:

{% set source = craft.entries.sectionId(10).first().gallery.type('gallery').first().entries.relatedTo(entry) %}

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

Next: {{ nextEntry.title }}
Previous: {{ prevEntry.title }}

Where SectionId(10.first() is pulling the Single entry and gallery.type('gallery').first().entries is pulling the Entries field within the Matrix.

Unfortunately this is producing blank Next and Previous links.

Next:
Previous:

I have referred to other questions regarding params and relations, although through experimenting with different solutions I am not queuing up the correct Next and Previous entries.

Neither is Craft providing any error reports regarding the blank state.

Any help is greatly appreciated.

In this particular case, .relatedTo(entry) is not necessary. So long the entry the following code is located within is within the entry within the source the pagination will populate. Otherwise these will remain empty.

{% set source = craft.entries.sectionId(10).first().gallery.type('gallery').first().entries %}

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

Next: {{ nextEntry.title }}
Previous: {{ prevEntry.title }}


How to render an entry type of a Matrix in HTML? <a href="{{box.learnMoreLink}}"> {{ box.learnMoreText }} </a>

Currently I have a Matrix field that has two plain-text fields. I want to change the href ({{box.learnMoreLink}}) from plain-text to an entry. I am trying to figure out how to render the entry field. Just changing the field type in the CMS is resulting in content loss. Anyone know the best way to go about this?

If you change the entry type then you're going to lose content for sure.

If changing that field type to an entry is really what you want, great. You could do something like

{# grab the first entry that we've selected #}
{% set learnMoreLink = box.learnMoreLink.first() %}
{# spit out the url for the first entry #}
{{ box.learnMoreText }}


Use sequential numbers for entry title I have a channel where I need each entry's Title include a sequential number, like this: 10003 - Entry Title
Is there a way to prepend a sequential number to the entry title?

I think you'll need to implement this with the Elements::EVENT_AFTER_SAVE_ELEMENT event and keep a record of the number.
If it doesn't need to be sequential 1,2,3 you could use a dynamic title and use {{object.sourceId}} which would be the entry id which will always increment


How do I setup my Element Types Sources for deep linking? In the Entries tab in the Control Panel, I see a list of Sources on the left hand side:

All Entries
Singles
News

When I click on each of these sources the page filters the appropriate results in the body and the URL gets updated appropriately:

All Entries => /admin/entries
Singles => /admin/entries/singles
News => /admin/entries/news

This is nice as I can now send links to other people to a specific sub-section in the sources, with the contents already filtered.

I've compared my code in the source nav to the code on the Entries Element Index page, and they are comparable, including passing the data-handle value to each source. But it's still not working in my Custom Element type. I must be missing something but I haven't yet figured out what.

How do we get this behavior working for custom Element Types?

Your plugin has to create those routes — via registerCpRoutes() — to match your desired URL structure.

Routes either trigger a site template or a controller, as described in the Routing docs. (Craft's own internal convention is for CP routes to trigger a controller method, which sets up the request and renders your desired template.)

You can look at Craft's own CP routes for inspiration in setting up your own; they're defined in /app/etc/config/common.php.


Can't access Pending user's profile info I have public user registration enabled with the "Verify email addresses" setting checked.

User registration form includes these "action" and "redirect" hidden fields:

<input type="hidden" name="action" value="users/saveUser">
<input type="hidden" name="redirect" value="signup/payment/{id}">

User's ID is coming through correctly in the last segment of the URL, but I can't fetch their profile. This is throwing a template error:

{% set userId = craft.request.lastSegment() %}
{% set profile = craft.users.id(userId) | first %}

But if I hardcode an existing Active user's ID it works:

{% set profile = craft.users.id(30) | first %}

Is there a way to access a Pending member's (albeit limited) profile info? What I really need to do is insert their email address into a subsequent form on the success page.

This works:

{% set user = craft.users.id(craft.request.lastSegment).status('pending').first() %}


Override max-length on the Title format field We're using entry properties in the Title format field to automate titles for some channels. However we've ran into the issue of this field having a max-length set on it. I understand why this exists when you create an entry. But when you're setting up the code to auto generate titles you can easily run longer than the allowed 255 characters.

Is there a way to change the max length or some way to get around this issue?

We've looked but haven't found any plugins to deal with this issue nor any clever ways to get around the current limitation. I've seen some posts about the max length but they relate to when you add entries. This is just about when you setup automated titles.

See reply from brandonkelly on GitHub for an alternative to adress this issue.

https://github.com/craftcms/cms/issues/5132#issuecomment-544507473


Matrix Table Content not showing I have a matrix table field that I want to render on a page. I've tried a few different things and nothing is working. I tried switch and elseif, but those weren't working. I'm no longer getting errors, but now - even though I have content in the fields - nothing shows up on the page.

It seems like it must be a templating error but I can't see what it could be. Any help would be greatly appreciated.

{% for block in entry.comparisonChart %}
{% if block.type == 'compareChartHeadingBlock' %}

{{ block.compareChartHeading }}

{% endif %}

{% if block.type == 'compareChartTwoBlock' %}
    {% for row in block.compareChartTwo %}

{{ row.chartTwoLeft }}

{{ row.chartTwoRight }}

     {% endfor %}
  {% endif %}

  {% if block.type == 'compareChartThreeBlock' %}
    {% for row in block.compareChartThree %}

{{ row.chart3Left }}

{{ row.chart3Center }}

{{ row.chart3Right }}l

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

Here is the matrix field:

First, make sure you have devMode enabled so any errors will be show. Then, I would consider writing the template code in a way that will ensure something will output when looping through the block types to help troubleshoot.

For example

{# Loop through each block #}
{% for block in entry.comparisonChart %}
    {# Output templating based on the block type #}
    {% switch block.type %}
        {% case "compareChartHeadingBlock" %}

{{ block.compareChartHeading }}

        {% case "compareChartTwoBlock" %}
            {% for row in block.compareChartTwo %}

{{ row.chartTwoLeft }}

{{ row.chartTwoRight }}

            {% else %}
                Compare chart two has no content
            {% endfor %}

        {% case 'compareChartThreeBlock' %}
            {% for row in block.compareChartThree %}

                        {{ row.chart3Left }}

{{ row.chart3Center }}

{{ row.chart3Right }}l

            {% else %}
                Compare chart three has no content
            {% endfor %}

        {% default %}
            {# The message below will be displayed if the type doesn’t match those handled above #}
            This {{ block.type }}’s templating has not been handled

    {% endswitch %}

{# If the Matrix has no blocks, output a message #}
{% else %}
    This Matrix has no content
{% endfor %}

An approach like the above should help narrow where the problem is occuring. If you do get error messages, please post them as it can help identify where the problem is occuring as well.


Localized Site -> howto redirect Browser How would you redirect users with an "english browser" automatically to the english site? I have no idea if this can be made with craft or if this is an apache webserver thing. Any idea?

'domain.de' => array(
    'siteUrl' => array(
        'de' => 'http://domain.de/',
        'en' => 'http://domain.de/en/',
    ),
),

Here is what i have done. Not sure if it helps you. I can't add comments. So here you go. This is based on geo plugin

Plugin serviceclass:

//to get local ele
private function getLocalElement()
    {
        $source=craft()->request->getRequestUri();
         if($source==''){
             $source = 'home';
         }
        return  craft()->elements->getElementByUri($source);
    }

//finds locale and redirect
private function redirectToLang()
   {
       $value=$this->detectBrowserLang()."_".strtolower($this->detectCountryCode());
       if(in_array($value, craft()->i18n->siteLocaleIds)==1){
            $element=$this->getLocalElement();
            if(!is_null($element)){
                $localElementUri = craft()->elements->getElementUriForLocale($element->id, $value);
                header('Location: '.$this->configBaseUrl().'/'.$value.'/'.$localElementUri, true, 302);
            }
        }

   }

//browser lang
private function detectBrowserLang()
   {
        $browserLang=craft()->request->getBrowserLanguages();
        if(isset($browserLang)){
            $lang=substr(strtolower($browserLang[0]),0,2);
            return $lang;
        }
   }

//detect country code by geo
private function detectCountryCode()
    {
        $info=$this->getInfoGeo();
        $countryCode=strtoupper($info["country_code"]);
        return $countryCode;
    }

Basically checking browser lang and country code(geo) with craft locales.


Assigning Image to lineItem? Our Shop-Customers should upload an image per Item they add to the basket. I managed to upload the image and insert it to an asset folder.

How can i assign the image to the lineItem (maybe as an option)?

This didn't work, as options is not writable:

craft()->on('commerce_lineItems.onBeforeSaveLineItem', function($event){
    $imageId = craft()->ultraschall->uploadCustomerImage(); // add image to asset folder
    if(isset($imageId) && is_numeric($imageId)){
        $lineItem = $event->params['lineItem'];
        $lineItem->options['imageId'] = $imageId;
    }
});

I got a solution.
You can't overwrite array elements at this point, but the whole array. I also found it better to use the event "commerce_cart.onBeforeAddToCart".
My working code is now:

craft()->on('commerce_cart.onBeforeAddToCart', function($event) {
    $imageId = craft()->ultraschall->uploadCustomerImage(); // add image to asset folder
    if(isset($imageId) && is_numeric($imageId)){
        $lineItem = $event->params['lineItem'];
        $options = $lineItem->options;
        $options['image'] = $imageId;
        $lineItem->options = $options;
    }
});


Categories, Single and Channels ....SEO Background... I took a look at this post answered by @Damon

My objective is similar.  I have a channel for news.  Each entry in news is assigned various categories (e.g. product category).

I do not have a "single" in Craft for each product category.  However, I do have a _productCategory.html template.  And each product category has its own page. ...that is, productCategory/{slug} with {slug} being an individual product category.   And I have a link to each product category in my nav.   I know, pretty basic.

I know there are multiple ways to skin the cat, but am I missing out on anything by not using a single for each product category page?  Is there any impact on SEO?

Here's some things to consider with SEO and URLs:

Readability of the url
Including keywords in the url
Shorter > longer
Fewer /folders/ in the url
Generally don't want any caps in the URL
Separate words with hyphens or underscores

So, "/particular-product-title" would be preferable to "/productCategory/particular-product"

Hope that's helpful!


Access data when posting to controller from front-end I'm writing a plugin to notify authors when a Disqus comment is posted. There is a Disqus JS callback you can use to hook into this, so I'm doing the following on the front-end:

this.callbacks.onNewComment = [function(comment) {
  var commentNotification = new window.VIGET.CommentNotification();

  commentNotification.notify('{{ actionUrl("vigetDisqus/notify/notify") }}', comment, {{ entry.id }}, {{ entry.author.id }});
}];

So I am passing the actionUrl of my controller, the comment itself, the entry id, and the author id. This all works perfectly fine, and I am passing it as data along as an AJAX request to the controller.

CommentNotification.prototype = {
  notify: function(actionUrl, comment, entryId, authorId) {
    var data = JSON.stringify({
      comment: comment,
      entryId: entryId,
      authorId: authorId
    });

    xhr({
      uri: actionUrl,
      method: 'POST',
      body: data,
      headers: {
        'Content-Type': 'application/json',
        'X-Requested-With': 'XMLHttpRequest'
      }
    }, function(err, resp) {
      console.log(resp.body)
    });
  }
};

How do I access the posted data inside my controller? I thought I could use the getPost method, but I am always getting null.

<?php
namespace Craft;

class VigetDisqus_NotifyController extends BaseController
{
    protected $allowAnonymous = true;

    public function actionNotify()
    {
        $this->requirePostRequest();
        $this->requireAjaxRequest();

        $authorId = craft()->request->getPost('authorId');

        $this->returnJson(array('authorId' => $authorId));
    }
}

Turns out the ajax library I was using was expecting the data to be passed in a serialized format:

'comment=' + comment + '&entryId=' + entryId + '&authorId=' + authorId

With that as the body of the request, the data became accessible to my controlled by using craft()->request->getPost


Trouble with Twig `embed` tag I'm trying to embed the sidebar and define which blocks to display.

{% embed "_partials/sidebar" %}
    {% block instagram %}{% endblock %}
    {% block subscribe %}{% endblock %}
{% endembed %}

sidebar.html is

{% block subscribe %}
    block content
{% endblock %}

But it doesn't show anything and no errors as well (dev mode enabled).

The idea is make a dynamic sidebar and define which widgets I'd like to see in each template.

This is what I use right now.

        {% set widgets = {
            'about'     : true,
            'instagram' : true,
            'menu'      : false,
            'recipes'   : true,
            'subscribe' : true
        } %}

        {% include "_partials/sidebar" with {
            widgets: widgets
        } %}

sidebar.html

       {% if widgets.menu == 'true' %}
           content
       {% endif %}

is there any other more flexible approaches for this?

I'm going to assume that, as per the use cases in the documentation, embed is a good fit for your requirements.

If you're not sure, extends and include are probably a better choice, as they're much easier to understand and work with.

Moving on, in your example you appear to have confused the roles of the template being embedded, and the template doing the embedding.

Here's how it should look:

{# Page (doing the embedding) #}
{% embed "_partials/sidebar" %}
    {% block subscribe %}
        The custom subscribe block content.
    {% endblock %}
{% endembed %}

{# Embed (being embedded) #}

        {% block subscribe %}
            The (optional) default subscribe block content.
        {% endblock %}


Plugin Development (Craft 3): Pass variables with redirection I'm building out a Craft 3 plugin and can't see who to pass variables with redirection from a controller.

For example, I have a controller that I want to pass back to the defined redirect value along with a variable, eg:

return $this->redirectToPostedUrl( ['order' => $order ] );

However, trying to access the order variable within my template is returning empty. The order object definitely exists before the redirection as it can be accessed from within my controller.

Any suggestions appreciated - I'm sure am overlooking something quite straightforward!

Try this:
Craft::$app->getUrlManager()->setRouteParams([
               'variables' => ['order' => $order]
             ]);


Limit Users Signup to Users from Specific Domain I have an eLearning page people from a .gov domain need to access.  I want them to be able to sign up for a user account and get immediate access, but I only want people from within that domain and perhaps one other to have this privilege.  I would want to approve any other users before they gain access.  Is this possible?

Probably best to do all of this from a custom plugin (that way you can write the logic for the approval process).

But regardless, you can do something like this from the top of your template:

{% if craft.request.getServerName() is not "mydomain.gov" %}
    {% exit 503 %}
{% endif %}

And similarly any controller actions would have:

if (craft()->request->getServerName() !== 'mydomain.gov" )
{
    throw new HttpException(503);
}


Why will my custom "Entries" field not display anything? In my entry template I have the following...

{% set entry95 = entry.story1995 %}
{{ entry95.title }}

And this displays nothing. Debug mode is on and no errors are showing. The handle for the field is set properly. Other fields for the main entry are showing up, but nothing from this custom Entries field.

I can't figure out what I could be doing wrong here.

You need to put the entry in a for loop. Because even if there's only one entry linked to, it could still potentially be multiple entries!

{% for entry95 in entry.story1995 %}
    {{ entry95.title }}
{% endfor %}


Flush Compiled Templates Migration File breaks Craft Migration Setup from 3.0 to 3.3 I was attempting to upgrade my Craft CMS from 3.0 to 3.3.19 on my production site. I had tested this out on several dev environments and worked with no issue. However, when doing it live I ran into a yii/exception

  Exception: rmdir(/app/b4mhz722nsjh4/storage/runtime/compiled_templates/f1): Input/output error (/app/b4mhz722nsjh4/vendor/yiisoft/yii2/helpers/BaseFileHelper.php:399)

I checked the storage/runtime folder and I noticed there was no f1 directory so I'm guessing it stopped the upgrade with this exception when it tried to remove a directory that didn't exist. The runtime folder is git ignored and I believe they're temporary files anyway. I couldn't find any info as to why it would be trying to delete a directory that doesn't exist.

My question is was this just a freak bug? Any help in the right direction would be appreciated.

One thing to note is I had tried the setup initially (after updating my composer JSON and lock file with the new updated packages) and tried the setup from my siteurl but ran into a CORS error because our control panel base URL is actually different. And ran into this migration error when trying again from the correct domain. I'm wondering if that may have caused issues.

Would like to try the upgrade again but wanted a little more clarity if possible on why I ran into that migration issue.

rmdir(/app/b4mhz722nsjh4/storage/runtime/compiled_templates/f1): Input/output error

If Craft or PHP tries to delete a folder that doesn't exist, it won't fail, but will gracefully continue execution.

That error is an underlying operating system error that suggests there might be some probably with your disk:

https://askubuntu.com/questions/325343/unable-to-delete-file-rm-cannot-remove-input-output-error

https://askubuntu.com/questions/74105/how-do-you-repair-an-input-output-error-in-an-ntfs-partition

Craft attempts to clear the compiled templates folder at the end of an update, so the good news is, for all practical purposes, the update probably completed successfully.


Using Craft environment variable for Asset source subfolder I have an environment variable "bucketUrl" that I would like to use as the subfolder path in my S3 bucket. However, Craft is not parsing the variable. When I upload an image, I see in my S3 bucket that a new subfolder "{bucketUrl}" was created with the uploaded image inside it. Why is Craft not parsing the environment variable? Craft is parsing my site url variable I am using elsewhere in the Craft admin, so I'm not sure why Craft is not parsing the bucket url variable.

From the docs, environment variables are currently only parsed in 3 places in the control panel.

File System Path (in asset source settings)
URL (in asset source settings)
Site URL (in Settings → General)

So they won't work in the "subfolder" setting.  You can add a feature request if you think that should change.


Craft 3.1.7 live preview multi-site only works on home page I am running sta-A and site-b on same installation.
I have cookie set for domain and have htaccess with CORS origin set to allow *, and also updated the nginx config to allow CORs. I know this last one works as font-awesome was blocked and is now working once i had updated the local nginx conf file.

The second domain only has live preview available on its home page. Any other entries created for the second domain have the link icon in the entries list in CP but when editing have no live preview option.

I thought 3.1.7 tokenized this?

Are those the fields on the non-visible entries translatable by site? It's the most common problem, not setting up some of the fields or subfield as translatable by site.


Get children from a Structure entry I'm new in the Craft CMS world. Today I start so build my first website with Craft.

I have a Structure with 2 Levels. Now I want so get the children from level 2. The level 1 entries are overview-pages for the content in the level 2 pages. I've build 2 entry types. One for the content and one overview pages.

Thx for your help :)
Alexander

If you need to get the level 2 children for a specific Structure entry, and you have that entry's EntryModel (i.e. you have an entry variable which refers to the Structure entry), you can just use the EntryModel's children property, appending level to only pull children from the desired level:

{% set children = entry.children().level(2) %}

There's also a descendantOf parameter which can be used in a craft.entries query – obviously, this should be the Structure entry's ID (or the complete EntryModel, i.e. entry):

{% set entries = craft.entries({
    'section' : 'yourSectionHandle',
    'level' : 2,
    'descendantOf' : entry.id
}) %}

Also, if you want to pull entries at a certain level in a Structure section but not limit it to children of a certain entry, you can append the level parameter to your basic craft.entries query:

{% set entries = craft.entries.section('yourSectionHandle').level(2) %}

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

Note that craft.entries queries can also be typed out using object notation, if you prefer (I find the object notation more readable, especially if you have a lot of parameters):

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


Where should PHP file of custom widget be in? I would like to develop my custom widget as this document in Craft 3.
https://docs.craftcms.com/v3/extend/widget-types.html#registering-custom-widget-types

However, it does not tell me where the PHP file should be in. I suppose it is not under vender/craftcms, because it would be deleted by Craft update. I wonder if you could tell where.

If it were my project, I would probably put the PHP file in modules

Here's some more info https://docs.craftcms.com/v3/extend/ and here: https://docs.craftcms.com/v3/extend/module-guide.html


Swapping Hogan for other JavaScript template engine in the SearchPlus plugin For a JavaScript novice like myself, what steps would be involved in swapping out the hogan.js templating framework for something else? I have my eye on Swig, which comes with some 'twig-like' filters I need to utilize when outputting my search results.

Hi, Developer of Search Plus here.

Swapping out the js template engine isn't a simple thing. It certainly can be done, but it'd involve a reasonable amount of reworking to change.

If you're less experienced with js I wouldn't recommend it off hand.

Instead of swapping out the javascript templating engine, I'd recommend using the alterBasicMapping (that's exactly what it's designed for) hook to change the actual content to the format you need before it's passed to algolia for indexing

If you did want to dig in and give it a try, the first step would be to create your own clone of the bundled searchplus.js, found in the /plugins/searchplus/resources/js/ folder.

Within that there are a few key parts, from line 48 you'd see the various Hogan.compile markers which would need changing, and then each of the separate renderHits(), renderFacets(), renderPagination() etc.. would need updating.

Most of those methods are dedicated to handling the logic, with the last lines of them finally passing the data down to Hogan, which looks like : $hits.html(hitsTemplate.render(content)).

Your swig version would replace that hitsTemplate.render() part.

Again - not something I'd directly recommend unless you're comfortable with the javascript side of things.


Channels within Structures? I have a site that requires the client to reorder their entries in each 'category' manually. Obviously structures are perfect for this but where I'm running into trouble is that the entries need to appear in multiple 'categories'.

Eg. Project One needs to appear in /projects and /selected-projects, both of which need the ability to be reordered via drag and drop functionality.

As far as I know using Craft's categories isn't an option as they can't be reordered so I'm trying to set this up with one channel that contains the entries and then using multiple structures and using the entries field so the client can add the entries they create in the channel to the structure.

Long story short, is it possible to display channels within structures?

I think you solved your own problem — by linking channel entries to structure entries using relationships (via the "Entries" field) you can display the same project in multiple locations. Seems like a perfect solution.


Front end member uploader Hi I'm fairly new still to CraftCMS. I built one website with it a few years ago and have tinkered with it ever since and I do like it a lot. What I've been asked to do is create a website directory for front end users to create an account and add their own content. It sounds like it might be beyond my ability though. Normally I develop in Wordpress (building bespoke themes and scripting custom fields) but even with something like this I would still resort to a plugin. Is this something that can be done fairly straight forward with Craft or do you know of a plugin for Craft that would achieve this?
Each account should get approval by admin before going live. They can then upload a profile picture, bio, gallery of images, text, video, and pdf and change password, email and other user details. It should also have it's own interface styling rather than Craft CMS back end interface. I have attached a crude example of what I have been asked to look into.
If you could give me a few pointers as to where I should look to see if it's something I could take on then that would be a great help.
Thanks very much.

At a basic level, front-end user account management is definitely something that can be done with Craft Pro natively.
There's a knowledge base article on the subject here: https://craftcms.com/knowledge-base/front-end-user-accounts

Each account should get approval by admin before going live.

Also possible natively, with the "Suspect users by default" user setting (Settings->Users->Settings in the Craft control panel.

I'm not saying you won't have to use a plugin (whether it's already built or a custom-built one), but depending on your specific requirements, you might be able to get way with natively functionality.


Long 'Deleting stale template caches' Is it common to have a (near)constantly running 'Deleting stale template caches' task ongoing? I commonly log in to see a task still pending several hours after the last change to the site was made, looking in the database the task usually has 50000+ 'steps'. Each step runs reasonably quickly (although it sometimes hangs) but the process appears to be taking up quite a lot of disk IO according to newrelic and clearly some pages are not getting their cache cleared for quite some time...

What could cause this and it it solvable?

If it's any help I have a reasonably large dynamic menu that i've put in 'cache' tags around and also have one channel with >1200 entries in it and the site is in 5 languages (although the channel with 1200 entries isn't localised) so this isn't a tiny site, performance still seems sluggish at times however.

The {% cache %}, by default will cache it's contents on a per URL and per locale basis.

A lot of times when we see the behavior you're seeing, that's not the desired behavior and you should be using the {% cache globally %} parameter, where Craft stores the cached segment only on a per locale basis and drastically reduces the number of rows in the database table.

I'd inspect everywhere you're using the tag and if it makes sense to use globally parameter, swap to that.

You can then clear the contents of your template cache tables (under Settings->Tools->Clear Caches Tool) and the database tables shouldn't grow anywhere near as large, letting the delete stale template caches task run faster.


Model/Record AttributeType documentation? I'm building a plugin which creates a few tables, and need to store some fairly robust data. I've done this before and previously gotten by with mostly AttributeType::String and AttributeType::Mixed, but this time I'd like to ensure I'm doing things by the book. Problem is: so far as I can tell, nobody's written the book.

I started out by Model and Record documentation, but they don't reference the possible AttributeType options. Next I read the class reference, but this isn't helpful either. Then I looked at the ModelHelper and DbHelper code. These were a bit helpful, but they don't explain how exactly an AttributeType affects throughout Craft. Eventually I found Experience's Definitive Guide to Validation in Craft series (specifically the linked AttributeType entry). This is quite helpful, but because it's focused mostly on validation, it doesn't answer many of my questions.

It's possible that the book by Experience answers gives more detail, but I'm surprised I need a book to learn about this. It also seems like a slight gamble, as I'm only potentially interested in one chapter right now.

Here's the sort of thing I'm hoping to learn:

What is the Name type used for?
What's the difference between Handle and Slug? Why choose one over the other?
What exactly does Template do, and why does it need its own type?
What's the difference between Url and Uri? Is it just the validation?

Maybe it's not important to know these things, but I think it would be helpful to understand what I'm doing and how these types are processed and affect the system. It's also not completely clear what types are available, as the ModelHelper source doesn't list types like String. I assume that's getting inherited from Yii, but I'm not certain.

Question:
Is there some documentation, or blog post, out there that explains the types available through AttributeType?

Problem is: so far as I can tell, nobody's written the book.

That's partly our fault... we've never really documented the Attribute parts of Models and Records.  And it probably won't happen now since the majority of that has been stripped out of the upcoming Craft 3 making it much easier to follow Yii 2 conventions (which happens to be way more documented).

  What is the Name type used for?

In the context of a Record, it's a shortcut for saying you're going to get a varchar datatype set to 255 chars.  In the context of a Model, it'll just enforce the 255 character limit.

  What's the difference between Handle and Slug? Why choose one over the other?

A handle is a varchar(255) that has a few pre-defined reserve words.  id, dateCreated, dateUpdated, uid, title.  Currently used in Craft for defining the handles that things like Asset Sources, Global Sets, Asset Transforms, etc. uses.

There isn't a AttributeType::Slug.

  What exactly does Template do, and why does it need its own type?

It's just a shortcut for a varchar(500), currently used in Craft when defining a template path for Category and Section settings.

  What's the difference between Url and Uri? Is it just the validation?

Semantically, a URL is a subset of a URI: https://danielmiessler.com/study/url-uri/

In the context of Craft, yeah - the only practical difference is the validation.


{% Exit 404 %} doesn't work right with routes The {% exit 404 %} doesn't work right on routed templates.

It's fine on pages that aren't affected by routes. Mysite.com/asdfasdf shows me the proper 404 page.

I've got some routes configured like this:

URL: projects/type/*
Template: _projects/category.twig

URL: projects/*
Template: _projects/entry.twig

In the top of entry.twig, I've got code that says:

{% set entrySlug = craft.app.request.getSegment(2) %}
{% set entry = craft.entries.slug(entrySlug).one() %}

{% if entry is not defined or entry is null %}
    {% exit 404 %}
{% endif %}

{# regular page template below here #}

mysite.com/projects/WorkingProject - this works right.
mysite.com/projects/BrokenProjectLink - gives me a 500 error.

When I turn on dev mode, the Yii debugger gives me a 404 ( HTTP 404 – Not Found – yii\web\NotFoundHttpException ), which is the right thing. But turning devmode off, I don't get the 404 page, I get my 500 Internal Server Error page instead.

Again, 404s for pages that don't have any routing work fine. It's just things that are getting routed, and using the {% exit 404 %} code.

This all worked in v3.3.20 and earlier, but it doesn't seem to work the same in Craft 3.4.0.2.

When a route is accessed, entry isn't automatically defined.

The actual value for * is available in the any variable in your template—see this example:

Route: projects/type/(*)
Template: _test

{# templates/_test.twig #}
Substituted route param: {{ any }}

Do note that entry is not automatically set by Craft for any custom routes! It's your responsibility to take the incoming value (in your case, any) and look up the Entry, within the template, or bail if nothing is found:

{# We can totally skip the test for `any`, because this template is only loaded when there's a non-zero-length value in the route: #}
{% set entry = craft.entries({ title: any }).one() %}

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

{# At this point, you've set `entry`, and can use it however you like! #}
{{ entry.myFieldHandle }}

  I'd recommend reviewing the requirements for your route, and consider using a more specific token in your route (i.e. (slug)), and matching based on a more stable value—titles can change, but IDs should stick around, and slugs are less prone to editing!


The license located at config/license.key belongs to X I have an error appearing on my site:

This site is the production version of the site - before hand there was a staging version and a test version.
The test version (hosted on the same server, does not have this error).
So my question is how do I generate a new License? this is a solo version of craft btw not a pro.
I have deleted the license in config/license.key - hoping this would generate a new one and the problem would be over - a new license was generated but the message remains.
Any help would be great -
Thanks - W

Go into Utilities > Caches > Clear Caches. I can't remember exactly which cache, but try all of them (maybe untick the asset transforms ones so you don't unnecessarily regenerate transformed assets).


Possible to change style of password reset page Is it possible to change how the password reset box appears when a user requests a password reset? Ideally we would like to include the same functionality but within a page that we have control over so that it looks like the same website users are used to.

Set the setPasswordPath config setting to a template in your craft/templates folder and you style the page however you want.

The form itself would need to be similar to the "Set Password Form" template example in the docs.


Structure unable to find _entry template I have a Structure named "pages" which is set to use the template named "_entry".

When trying to visit one of the pages I’m just getting a blank screen.

The Craft log shows an error in the template loader because it can’t find a template.

  Craft\TemplateLoaderException: Unable to find the template
  "about/index". in
  /path/to/site/craft/app/etc/templating/twigextensions/TemplateLoader.php:123

The structure is set to use the template named _entry which is present and all as it should be.

I have tried renaming the template to no avail.

Other parts of the site are working fine. It only seems to be this Structure that has a problem.

The problem is occurring on an Azure VM running Ubuntu 16.04 LTS with PHP 7.0, running MySQL 5.7 with Strict mode disabled and managed with ServerPilot. I'm pretty sure it's been working OK since I deployed to Azure a couple of days ago but I can't explicitly remember testing these pages since my involvement has largely been on a different part of the site (which is working OK).

This is working fine locally, and has been working fine on a test server set up at Digital Ocean (I've decommissioned that but I'm in the process of setting it up again to test this).

Update: I can confirm the same code works perfectly on the Digital Ocean/ServerPilot combo so it appears to be something Azure or possibly MySQL 5.7 related (the Azure deployment is using MySQL 5.7 with Strict mode disabled)

Update: I'd incorrectly read the error message. The _entry template appears to be found. But this is then trying to load another template (in this case about/index) which is where things fail.
There is no about/index template it should fall through to a generic template.

{% if craft.request.getSegment(2) %}
    {% set internal = craft.request.getSegment(1) ~ '/' ~ craft.request.getSegment(2) %}
    {% set index = craft.request.getSegment(1) ~ '/index' %}
{% else %}
    {% set internal = entry.uri ~ '/index' %}
    {% set index = entry.uri ~ '/index' %}
{% endif %}

{% include [internal, index, '_generic'] ignore missing %}

Got to the bottom of it!

The _entry template relies on the fact there's a template error.

On the production site I'd added,

'suppressTemplateErrors' => true

to the config, which stopped the behaviour that was being relied upon to serve the generic template


Recommended way to provide user feedback in the control panel? Is there a recommended way to provide user feedback in the control panel — something like a modal window with a simple 'ok' button to dismiss?

I am writing a plugin that syncs data between users, another channel ('accounts'), and an external service (Braintree), using saveEntry and saveUser events to create/update related records as needed. I would like to provide user feedback in the way of a modal window that reports what related records were created and/or updated. What would be the recommended 'Craft' way to implement this user feedback modal? Or is there something already built-in to support this and how might I access it? I see some advice here regarding generating a generic modal window, but not sure the best way to integrate this within my plugin. Any advice would be appreciated even if very general.

To me, this seems like a great use case for a custom dashboard widget.


How to pull extra data with a user Users, by default, do not have middle names. So let's say I create a table with a foreign key linking to the user id, this table will contain middle names. How would I tell craft to join the middle name data? Could I create a plugin with a hook that gets middle name whenever user data is pulled? Where do I begin?

You can add custom fields to users the same way as you do for entries, categories, and all other elements in Craft. Create a custom field for middle name, and go to Settings > Users > Fields and add that field to the field layout.

EDIT:
The field will show in the profile tab, and there is no way to properly add fields to the account tab, even with a plugin. But, although a bit hacky, you could do this by just moving the field with javascript.

First, install the Control Panel JS plugin by Lindsey DiLoreto. Read the docs on how to get the plugin to load your custom js-file.

Each custom field in the form has an id with the naming convention fields-myCustomFieldHandle-field. If you name the field middleName and want to put it before the email field on the account tab, you could do something like this:

$(function () {
    if ($('#userform').length>0) { // just to make sure we're in the user edit page
       $('#email-field').before($('#fields-middleName-field'));
    }
});

Getting it to appear between the first and last name fields, or making them 100% width and putting the middlename in the middle, would also be possible, but requires a bit more DOM manipulation. Let me know if this is important for you.


Get transformed asset URL in controller I want to return JSON with some asset URLs, but i want these URLs to be transformed asset URLs.

Is there some way for me to get the asset transformed URL in the controller? Will the assets be automatically transformed or i need to somehow do it manually ?

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

Twig:

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

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

PHP:

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

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


Conditional for specific page I'd like to only load some scripts for 1 specific page with the Url /projects/.
Currently I'm using:
{% if craft.app.request.segments|first == 'projects' %}
 // load scripts
{% endif %}

This works.
However, I also have pages with the Url /projects/project-name which should not load the script.
How can you perform a conditional test for just the Url /projects/ ?
Thanks

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

On phone so ymmv


Issue Importing Data to Matrix Fields With FeedMe Plugin I am migrating content from a drupal site into Craft CMS. I am trying to using the FeedMe Plugin to do this.

Right now I'm working with a single test XML file to make sure my fields and setup are correct before I do the bulk import. However, my xml only ever creates the first matrix block. There is no limit to the number of blocks a user can include in the matrix block field I'm importing to.

The entry I am migrating content into has three tabs for fields. The main tab consists of the title and a matrix block. The third tab has a third party field "Legacy URL" from the Retour Craft CMS Plugin.

My XML looks like this:

<?xml version="1.0" encoding="UTF-8" ?>
<node_export created="Mon, 02 Oct 2017 00:15:47 -0400">
    <node>
        <title>Celebrating J Day</title>
        <nid>862</nid>
        <post_date>2017-09-22T00:00:00</post_date>
        <summary>A super summary.</summary>
        <storyBlock>
            <image>
                <image>http://website.com/path/to/my/image.png</image>
                <position>center</position>
            </image>
            <text>
                <text>Some awesome text is here.</text>
            </text>
        </storyBlock>
    </node>
</node_export>

My FeedMe field mapping looks like this:

The title, post_date, summary, and image matrix block all get imported properly. However, the text block and the nid into the legacy url field are not being imported.

The versions of everything:
FeedMe 2.0.7
Craft CMS 2.6.2991
PHP 7
MySQL 5.7

Does it look like I've set something up incorrectly? Any advice on how I can get this running correctly?

If any of the above is unclear, or if there is additional information I can provide, please let me know. I really appreciate your time and support!

I believe this has been fixed in the latest version of Feed Me (3.0.2.1 at time of writing). Do feel free to comment if not, or get in touch via the Feed Me support channels


Internal Server Error - getDateFormatter() on null When doing a manual update from 2.6.3012 to 2.7.8, I get the following error:

  Internal Server Error
  Call to a member function getDateFormatter() on null

I get the following error when enabling devMode:

Updating from the Dashboard fails too, but in a slightly more verbose fashion:

  [curl] 28: Operation timed out after 30001 milliseconds with 0 out of 0 bytes received [url] https://download.craftcdn.com/craft/2.7/2.7.8/Patch/2.6.3012/[redacted string of numbers].zip

Any help is welcome.

Craft support had suggested looking into the locales table, which had a singular entry for en_us.

What allowed me to update was to copy the following folder and its content: app/framework/i18n/data. It was entirely missing from the Craft-2.7.8.zip file I had downloaded.


Columns on the Entry index page giving errors For some reason whenever I add a custom column to a section's entry list I'm getting errors and no values.

If I add Entry Type to the column list, for example, it's saying:

Unknown class: Craft\EntryTypeModel

And links are saying:

Unknown class: Twig_Markup

I'm a little dumbfounded?  I tried removing and re-adding them and still no luck.  Any ideas?

So turns out it was an issue with an older plugin, DashCols. As soon as I disabled it things worked fine.

Unsurprising in hindsight!


Log to console / error window? I'm trying to get this code working

{% if article_id is defined %}
    {% set entry = craft.entries.id(article_id).first() %}
{% endif %}

The code itself is unimportant, what's relevant is that I'm currently working outside of the context where I would rendering an article. This particular code happens to be broken, and I would like to fix it via inspecting {{ article_id }}. Except I can't, because:

Template Error

A template that extends another one cannot have a body.

---

{% extends "_base" %}

{% if article_id is defined %}
    {% set entry = craft.entries.id(article_id).first() %}
    {{ article_id }}
{% endif %}

Now there's a variety of ways that I could solve this issue, but I'm wondering what's the best option. Ideally it would be something like {{ craft.log(article_id) }} - ie. a function would still produce the Template Error, but at also let me see the value / other information about article_id (either in the error window, or on the javascript console log).

How should I implement the logging behavior that I'm looking for?

If you have devMode enabled, then you have access to Twig's dump method that lets you inspect variables.

{{ dump(article_id) }}

Or, if you're feeling more adventurous, there is a debugging library called Kint that there is a Craft plugin for to help debug templates.


Basic Module Tutorial or Example I am having a difficult time understanding how to output even a simple variable using a module. Ultimately I have PHP code that I need to execute to generate a PDF. I managed to do this in V2.5. I'm following all the tutorials that I can find, bu none I feel aren't clear. Any recommendations on the simplest of examples, even if it's just outputting a variable.

Thanks

I haven't tried this tutorial yet, but having learned a lot about Craft 3 from Andrew Welch's other tutorials, I don't doubt this may have some nuggets of useful information to get you on your way.

https://nystudio107.com/blog/enhancing-a-craft-cms-3-website-with-a-custom-module


Can I output SVG code from an asset? Is there any way to output the actual source code from an SVG asset in Craft?

Rather than linking to it, I would like to embed the code in the page.

I tried a twig include, but I cannot include files outside the templates folder.

Thanks!

Check out my plugin Inlin, I made it exactly for this. :)


Guest user registration using Commerce 3 I have just started using Craft Commerce (only Lite version currently) and I'm currently trying to get to grips with what is possible. My question is regarding subscriptions.
The site that I'm working on needs to support subscriptions. It has a single, flat rate plan which would charge users monthly. Not only that but it requires that once a user/guest has subscribed to a plan, they are then registered as Craft users. So far I have set up the plan in Stripe and in Craft using the standard template below.
{% set plans = craft.commerce.getPlans().getAllPlans() %}

{% for plan in plans %}
<form method="post">
    <input type="hidden" name="action" value="commerce/subscriptions/subscribe">
    <input type="hidden" name="planUid" value="{{ plan.uid|hash }}">
    {{ csrfInput() }}

{{ plan.name }}

    {% set paymentSources = craft.commerce.
        getPaymentSources().
        getAllGatewayPaymentSourcesByUserId(
            plan.getGateway().id,
            currentUser.id ?? null
        )
    %}

    {# if we don’t have a saved payment soruce, collect details for the gateway #}
    {% if not paymentSources|length %}

            {{ plan.getGateway().getPaymentFormHtml({})|raw }}

    {% endif %}

    <button type="submit">{{ "Subscribe"|t }}</button>
</form>
{% endfor %}

When I try to submit this form it simply reloads the current page. Nothing is recorded in Stripe or Craft. Not too sure why this would be.
Ideally what I'd like is for a user to subscribe to a plan and simultaneously register themselves as a user on the site, so that they would be able to log in and out. Is Commerce able to support user registration when purchasing a subscription?

This can definitely be done, but I don't think it's possible to do it all in the same form without using a custom module to handle either creating the user programmatically and then submitting to the Commerce controller or vice versa.
Craft has support for creating a user account via a front-end form (see the User Registration Form in the Craft docs) but you can't submit to that controller and also submit to the Commerce subscriptions controller as per the standard example template at the same time.
It might be possible to achieve something close to what you're looking for by showing a user registration form first, and then set the redirect input for that form to the payment page. However, if you want to have the user logged in directly after registration but before payment in order to save the user's payment details etc., you're going to need to do some custom development work to log the user in programmatically first since the default user registration controller just creates the account but doesn't log the user in.
I've done this sort of process where the user account is created, then logged in automatically, then they enter their billing address and payment details, but that was using Commerce Pro and a multi-step registration/payment form which is a bit more complex than your use case.


Is it possible to set a hashed password programatically for a user? Related to this question - with one difference.

Is it possible to set a hashed password for a user? I'm able to save the user just fine - but when I pass the already hashed password like $user->password it doesn't set the password. I'm not seeing anything within $user->getErrors(), it's just a blank array. Any ideas?

There’s no API for it; you would need to save it to the database directly.

If any of the passwords are known to you, you should probably start by manually pasting that hashed password into your account’s password column, and verify that it’s actually going to work. Even if the old site was also using mcrypt, it’s still pretty unlikely that they get hashed the exact same way (different salts, etc.).

If it doesn’t work out, and you really don’t want to require everyone to reset their passwords, you could save all of your hashed passwords in a separate table, and write your own "login" controller action using a plugin. That controller action could:

grab the user by their given username/email

$loginName = craft()->request->getPost('loginName');
$user = craft()->users->getUserByUsernameOrEmail($loginName);

see if that user has a row in your old hashed passwords table
if so, fetch their password from post...

$password = craft()->request->getPost('password');

hash that password using the old site’s exact hashing method
if the hashed password matches the one in the table...
save the posted password on the user account

$user->newPassword = $password;
craft()->users->changePassword($user);

delete the user’s row in the old hashed passwords table (so we're only doing this once per user)
log the user in

craft()->userSession->login($loginName, $password);

(See craft/app/controllers/UsersController.php - actionLogin() for a full code example of login().)


Can't get Craft running on Heroku I'm familiar with Heroku, but new to Craft CMS.
In order to get a site running, I followed this tutorial: https://medium.com/@aj1215/craft-cms-on-heroku-79b991665b0b#.8b561b1b4

But the site isn't functioning. My Heroku app just results in: Application Error An error occurred in the application and your page could not be served. Please try again in a few moments. If you are the application owner, check your logs for details.

My development server runs fine. But I have no idea what I need to do to get the heroku app to function. I'm pulling my hair out.

I've tried everything I can think of, but can't get it to work. I'm not sure what I'm doing wrong.

These are messages toward the end of my Heroku logs:

2016–01–31T03:09:21.480751+00:00 app[web.1]: nginx: [emerg] “server” directive is not allowed here in /app/nginx_app.conf:1
2016–01–31T03:09:21.475721+00:00 app[web.1]: Starting nginx…
2016–01–31T03:09:21.481090+00:00 app[web.1]: Process exited unexpectedly: nginx
2016–01–31T03:09:21.481236+00:00 app[web.1]: Going down, terminating child processes…
2016–01–31T03:09:22.183035+00:00 heroku[web.1]: Process exited with status 1
2016–01–31T03:09:22.182791+00:00 heroku[web.1]: State changed from starting to crashed
2016–01–31T03:09:27.185620+00:00 heroku[router]: at=error code=H10 desc=”App crashed” method=GET path=”/” host=paradata.herokuapp.com request_id=1e502143–94ac-4aea-b34b-3087addd1d20 fwd=”172.11.56.78" dyno= connect= service= status=503 bytes=

enginx_app.conf file:

        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 on;
        }

this is my craft/config/db.php file:

<?php

$url = parse_url(getenv("CLEARDB_DATABASE_URL"));

return array(

    'server' => $url["host"],

    'user' => $url["user"],

    'password' => $url["pass"],

    'database' => substr($url["path"],1),

    'tablePrefix' => 'craft',

);

I solved it.

I needed to remove calls to 'server' and 'http' in my enginx_app.conf file. Now the file only makes calls to 'location'.


Cache issues making site super slow in production but not in dev mode We have a site that is performing very poorly with very long load times and I'm guessing it may be related to caching but have no idea how/why.

The site's homepage was loading very slowly while in development due to a mega menu with a lot of queries to create primary and secondary navigation. I cached that globally while in dev and the page performance improved about 70%. I did some further global caching {% cache globally %} for things like the site footer and than added some regular caching {% cache %} for entry-specific template content.

Once this was all done, performance was very good. However, then we launched the site and took the site out of dev mode (which is had previously been in). The launch was on the same account - nothing changed - just pointed the DNS to this account.

Since that time, performance has been poor again. Further, when logging into the control panel, we always see this (which we never saw while in dev mode):

What's odd also is the circle and bar progress indicators are always in the exactly pictured state - they're never more or less along in terms of position (over the course of weeks).

Lastly, if I go into the CP settings area and Clear Caches, performance seems to pick up again for a little while.

I'm at a complete loss as to what may be happening that is causing these issue and any help would be greatly appreciated.

Thanks,
Mike

This article (http://buildwithcraft.com/help/stuck-tasks) from Brad's comment was indeed the way to address this - and our logs did show this exceeding the php execution time. Thanks Brad!


Is it possible to search an asset filename stored on a remote Amazon S3 volume? I'm successfully using the .search element attribute to search asset filenames stored locally.

{% set mediaExists = craft.assets.folderId('6').search('filename:' ~ vLogID|slice(0, 5)) %}

Is it possible to search filenames stored on a remote Amazon S3 volume?

In my testing, it doesn't seem to be finding the remote files. It works when searching the local volume folderId('3') by not when the remote S3 folder folderId('6').

Background:
There is no direct relationship between an entry and assets. I upload all assets to the server via FTP and then index the volume in my Craft Control Panel. I can see the S3 asset in Craft CP and have cleared cache and reindexed the S3 folder source.

I am using a url query string to tell the template what the LogID is for the entry that is displayed. Then, the code searches the asset folder for any assets that contain that LogID number. If there are any matches, then those assets are displayed on the front end page in a slider.

I can see the S3 asset if I type in the direct asset url link so the permissions of Public seem to be set correctly.

This is my code that is searching the asset filename on the server:

<!-- grab log id and use slice filter  -->
{% set vLogID = craft.app.request.segments|last %}

<!-- Check to see if there is any media uploaded  -->
{% set mediaExists = craft.assets.folderId('6').search('filename:' ~ vLogID|slice(0, 5)) %}

The above code says:

Grab the LogID from the url query string (example: 12345).

Then, search the asset folder (set by folderID), search all of the files in the folder for any filenames that contain LogID (example 12345).

It works when searching the local volume folderId('3') but not when the remote S3 folder folderId('6').

I figured it out.  I was using folderID instead of volumeID.  It looks like this parameter changed from Craft 2 to Craft 3.


Get all entries attributed with category Maybe I'm going mad here, but I can't figure out how to get all entries which are in a certain category.
Following the syntax laid out here: http://buildwithcraft.com/help/entries-related-to-category
you'd think something like this would work, but I get nothing:
{% for entry in craft.entries.relatedTo('Naming') %}

'Naming' is my category, and I have several case study entries with that category attributed.
I also tried adding more params, like restricting it to just the case study section:
{% for entry in craft.entries.section('ourWork').relatedTo('Naming') %}
This would be outside the category page or related case study page btw, ie on the homepage.

Found an answer to this here: https://craftcms.stackexchange.com/a/4132/3890

The important thing to note is when you're using relatedTo you're not passing a slug, you're passing a whole object. So just .relatedTo('category-name') won't work.


getUrl using my original develpment server domain I have the following code and after moving site to a live server, the img src is using the old domain, however, the anchor links have correct domain name.  Any idea what the issue is?

                                {% for block in entry.threeHomepageImages.type('images') %}

                                                {% if block.image|length %}

                                                {% endif %}

{{ block.imageTitle }}

                                {% endfor %}

Have you checked the path of the asset source the image is in? Sounds like that might still be the old server's path.
Best practice is to use Environment-specific variables in your config file, and then use those in you Asset Source settings as well.

So, use {basePath}assets/site as your File System Path for instance (if you've used basePath as a config variable).

That way, it will adapt to whatever environment you're working on.


Craft 3 CMS Update Error I try to update my craft3 cms system.

Ошибка: An error occurred

Вывод: Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

Problem 1
- The requested package oneup/contao-security-checker-bundle could not be found in any version, there may be a typo in the package name.
Problem 2
- Installation request for craftcms/cms 3.0.22 -> satisfiable by craftcms/cms[3.0.22].
- craftcms/cms 3.0.22 requires enshrined/svg-sanitize ~0.9.0 -> satisfiable by enshrined/svg-sanitize[0.9.0] but these conflict with your requirements or minimum-stability.
Problem 3
- craftcms/cms 3.0.22 requires enshrined/svg-sanitize ~0.9.0 -> satisfiable by enshrined/svg-sanitize[0.9.0] but these conflict with your requirements or minimum-stability.
- craftcms/redactor 2.1.6 requires craftcms/cms ^3.0.0-RC15 -> satisfiable by craftcms/cms[3.0.22].
- Installation request for craftcms/redactor 2.1.6 -> satisfiable by craftcms/redactor[2.1.6].

Potential causes:
- A typo in the package name
- The package is not available in a stable-enough version according to your minimum-stability setting
see for more details.
- It's a private package and you forgot to add a custom repository to find it

Read for further common problems.
Running update with --no-dev does not mean require-dev is ignored, it just means the packages will not be installed. If dev requirements are blocking the update you have to resolve those problems.

Solution I've found is - to remove roave/security-advisories, but I still don't understand how I can do this. Same problems I have with plugin install.

Composer File

{
  "name": "craftcms/craft",
  "description": "Craft CMS",
  "keywords": [
    "craft",
    "cms",
    "craftcms",
    "project"
  ],
  "license": "MIT",
  "homepage": "https://craftcms.com/",
  "type": "project",
  "support": {
    "email": "support@craftcms.com",
    "issues": "https://github.com/craftcms/cms/issues",
    "forum": "https://craftcms.stackexchange.com/",
    "source": "https://github.com/craftcms/cms",
    "docs": "https://craftcms.com/docs",
    "rss": "https://craftcms.com/changelog.rss"
  },
  "require": {
    "craftcms/cms": "3.0.18",
    "vlucas/phpdotenv": "v2.4.0",
    "craftcms/redactor": "2.1.5",
    "dolphiq/craft3-forms": "1.1.0",
    "craftcms/contact-form": "2.2.2",
    "craftcms/guest-entries": "2.1.3",
    "nerds-and-company/schematic": "4.0.14",
    "symfony/yaml": "v3.3.6",
    "illuminate/contracts": "v5.5.40",
    "illuminate/support": "v5.5.40",
    "nesbot/carbon": "1.32.0",
    "psr/container": "1.0.0",
    "psr/simple-cache": "1.0.1",
    "symfony/translation": "v3.3.6"
  },
  "autoload": {
    "psr-4": {
      "modules\\": "modules/"
    }
  },
  "config": {
    "optimize-autoloader": true,
    "platform": {
      "php": "7.0"
    }
  },
  "scripts": {
    "post-root-package-install": [
      "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
    ],
    "post-create-project-cmd": [
      "@composer dump-autoload -o",
      "@php craft setup/welcome"
    ]
  }
}

thank for your answers

Try replacing your "require" section with this in your composer.json file:

"require": {
    "craftcms/cms": "^3.0.18",
    "vlucas/phpdotenv": "^v2.4.0",
    "craftcms/redactor": "^2.1.5",
    "dolphiq/craft3-forms": "^1.1.0",
    "craftcms/contact-form": "^2.2.2",
    "craftcms/guest-entries": "^2.1.3",
    "nerds-and-company/schematic": "^4.0.14"
  },

Then, if you have Composer installed from the command line, run composer update from your project's root and let it finish.


Registering a class library within a plugin I am trying to instantiate a class from a third-party library from within a controller. Probably not the best place to do this but just testing.

require(craft()->path->getPluginsPath().'myplugin/vendor/ifpk/src/fsdk.php');

$app = new fSDK;

I get the following error

Fatal error: Class 'Craft\fSDK' not found in /var/www/.../controllers/MyPluginController.php on line 57

Not sure where to go with this next.

Through the magic of PHP namespacing, all plugins fall under the Craft parent class by default.

Since you're accessing a library outside of the Craft scope, you'll need to prepend a backslash to your library's class name:

$app = new \fSDK;


"Giving your Plugin its own CP Section" What about the CSS? I'm working on a plugin with it's own CP section as described in the docs here. What is the appropriate way to include CSS styling for that page?

You can include CSS for your plugin one of two ways.

1) Inline CSS

You can include CSS snippets by using {% includeCss myCss %}. This is great if you are just wanting to include a few lines of CSS. Read more here: http://buildwithcraft.com/docs/templating/includecss

2) Reference a Resource CSS file

Usually contained in your /resources folder inside your plugin you can include a CSS file by using {% includeCssResource "pluginName/styles.css" %} You can read more here: http://buildwithcraft.com/docs/plugins/resources


Exclude "featured" entries from a "recent" entries {% for %} loop Here's my current setup:

Blog (Channel) - All of my blog posts will go here

Blog Landing (Single) - This section only has one field - a Featured Articles Entries field that lets me select 3 entries from the "Blog" channel.

Basically what I want to do on the Blog Landing section is have a dedicated area for the 3 Featured articles (ones that I will choose from that Featured Articles entries field), but then display the next 5 most recent articles that have not been selected as a Featured article in a different area.

I've successfully outputted my Featured Articles with this code:

{% set featured = entry.featuredArticles %}
  {% for entry in featured %}
    {{ entry.title }}
  {% endfor %}

And I can get my 5 most recent with this code:

{% set allEntries = craft.entries.section('blog') %}
  {% for entry in allEntries.limit(5) %}
   {{ entry.title }}
  {% endfor %}

I can't figure out how to exclude the entries from the Featured Articles area from the output of the Recent Articles area.

So say I have 10 entries in my Blog channel, (Post 1 is most recent, Post 2 is second most recent, and so on), and I've selected Posts 2, 4, and 5 as my "Featured" articles, how do I get it so that the 5 "Recent" articles display Posts 1, 3, 6, 7, and 8 instead of Posts 1, 2, 3, 4, and 5?

What you could do is get the ids of the featured element, and exclude those from the second craft.entries call. Something like this:

{# Get the ids of the featured items you got above #}
{% set featuredIds = featured.ids() %}

{# Get entries in section 'blog' which don't have an id in featuredIds #}
{% set allEntries = craft.entries.section('blog').id('and, not ' ~ featuredIds | join(', not ')) %}

{# Loop and output #}
{% for entry in allEntries.limit(5) %}
  {{ entry.title }}
{% endfor %}

The use of the join filter may seem a bit cryptic. But, when excluding one id from a list of entries, you'd do .id('not 3'). When excluding more than one, you need to specify the conditional first (the and part) and then a comma separated list of not (id). So the join basically creates a string like .id('and, not 3, not 4, not 5'), if the ids of the featured articles where 3, 4 and 5.

Edit: added necessary space to join(', not ')


Last header tag overwrites any previous tag with same name - expected behaviour? I am trying to add several header tags with the same name but different values. The last one prevails where the other don't appear to be output (when examining the output header using a sniffer). eg.

{% header "Link: </css/master.css>; rel=preload; as=style" %}
{% header "Link: </js/plugins.js>; rel=preload; as=script" %}
{% header "Link: </js/main.js>; rel=preload; as=script" %}

I'm trying to implement HTTP/2 server push for these files. Is this expected behaviour? Thanks

It looks like if you want to specify multiple values for a link header, you need to comma separate them: https://stackoverflow.com/a/25416118/684


Sprout Forms: Modify Entry In the Sprout Forms plugin, is there a way to modify the EntryModel through sproutForms.onBeforeSaveEntry? I have a plugin that sends a cURL request onBeforeSaveEntry, and I'd like to grab the response from that and deliver it to the user on the thank you page.

I've tried setting new properties on the $event object but I'm getting errors, so maybe my approach is wrong? Been searching, but unable to find how to get it done.

So it turns out you can modify an existing property like this:

$event->params['entry']->getContent()->existingProperty = 'new value';

What I ended up doing was using a hidden field and then updating the value of that from the sproutForms.onBeforeSaveEntry event:

craft()->on('sproutForms.onBeforeSaveEntry', function(Event $event) {
    $entry = $event->params['entry'];
    $entry->getContent()->subscribeStatus = 'success';
});

Since that property can be set depending on what the response is from the cURL post, it's possible to deliver success/error messages to users on the thank you page and prevent the subscribe from silently failing in the background.


How can I update a checkbox from a plugin? I have a plugin that is listening for a form submit.
Within that form are two fields firstName and agreeToTerms.

When the form is submitted, I am updating an existing entry with the values that were posted.

I can get all fields to update except my checkbox. I'm not sure what I need to send to craft if the user has checked the checkbox.

Here is what I have so far:

MyController

$postDateTime = ...

...
$entry->setContentFromPost(array(
    'agreeToTerms' => craft()->request->getPost('fields.agreeToTerms'),
    'firstName' => craft()->request->getPost('fields.electronicSignature'),
    'signatureDate' => $postDateTime
));
...

This returns "1" which is the value of the checkbox.

craft()->request->getPost('fields.agreeToTerms') // returns 1

But that isn't what I need to send to Craft. If I were using jquery, I am looking for something like

$.prop('checked', true);

EDIT

To help clarify in case someone else comes across this thread, as @carlcs stated I was in fact talking about a checkbox field.

The plugin I am using allows users to create entries in a section. When an entry is created, one of the fields is a checkbox. I was attempting to set the checkbox field as checked if the user had checked the corresponding checkbox when the entry was created.

If I understand correctly you're talking about a Checkboxes field type. Because you can have multiple checkboxes within such a field, Craft stores an array to the database.

Try if this works:

$entry->setContentFromPost(array(
    'agreeToTerms' => array(
        craft()->request->getPost('fields.agreeToTerms'),
    )
));


How to define table attribute in the record file Following code is working on Craft 2:
class My_TableRecord extends BaseRecord {
  public function getTableName() {
    return 'my_table';
  }

  protected function defineAttributes() {
    return [
      'title'         => AttributeType::String,
      'description'   => AttributeType::Mixed
    ];
  }
}

According to this documentation the defineAttributes() is not available in Craft 3. So how can I define table's attributes in Craft3 to complete following code:
class My_TableRecord extends ActiveRecord
{   public static function tableName()
    {
        return '{{%my_table}}';
    }

  //equivalent function of defineAttributes() of Craft3 will go here

}

So how can I define table's attributes in Craft 3 to complete following code:

You don't.
By just defining the table name, that gives Yii enough information to reflect on the underlying columns for the table.
You can add property doc blocks to get type-hinting in your IDE for the columns.
Probably also worth reading: https://docs.craftcms.com/v3/extend/updating-plugins.html


CSRF token is null or empty in craft 2 I'm having an issue with Craft 2.6 and the CSRF token. I enabled Csrf Protection in my general.php file by adding this line $config['*'] array so it looks like:

$config['*'] = [
...
    'enableCsrfProtection' => true,
...
],

I also tried adding this line to the section for // Global variables after this array, but still no luck. I try to attach the token to the window object like this:

<script>
        window.csrfTokenName = "{{ craft.config.csrfTokenName }}";
        window.csrfTokenValue = "{{ craft.request.csrfTokenValue }}";
</script>

and the window.csrfTokenName = "CRAFT_CSRF_TOKEN"; but window.csrfTokenValue = "";

I can't figure out how else to get a csrf token and I can't find any documentation that says anything else. I'm just trying to see if I'm missing something really easy or if there is actually something else I need to add. Any help is greatly appreciated!

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

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

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


How to use SSL for local development with Nitro? I've created a new Craft CMS project and installed Nitro to run everything in a VM. Now I'm wondering if it's possible to use SSL for the local domain? I didn't found anything in the documentation.

Checkout Nitro 2, it now has full SSL support
https://craftcms.com/docs/nitro/2.x/commands.html#trust


Drop-down and checkbox in a condition I'm new to Twig, and I'm struggling to compare a value from a checkbox with a value from a drop-down

   {# sourceCountry - checkbox with a list of countries #}
   {# currentUser.country - dropdown with a list of countries #}

   {% for sourceCountry in region.targetCountries %}
      {{ sourceCountry }} = {{ currentUser.country }}   <br>
      {{ dump(sourceCountry == currentUser.country) }}
      {% if sourceCountry == currentUser.country %}
         {% set visibility = true %}
      {% endif %}
   {% endfor %}

The result I'm getting from this is:

GB = GB

bool(false)

Most likely something to do with variable types, but no idea how to solve this. I've searched for some Twig 'to string' conversions, but no luck.

A checkboxes field returns an array of models, that you can inspect using {{ dump(sourceCountry) }} in your loop.

The model has a __toString method that outputs the checkbox value when you output the model using {{ sourceCountry }}. This magic method doesn’t do its thing when you use the model in a comparison operator, so you are currently comparing a model to a string.

Access the value property directly and your conditional should work.

{% if sourceCountry.value == 'GB' %}
    {% set visibility = true %}
{% endif %}


How to Update an If Rule Based on Different Parameters Passed to a Macro? I have a macro that can take up to six parameters which serve to populate nav links. The parameters are basically grouped into twos, with someone needing to pass in both a link and a title to make a nav link.

Below is my current code, which works as intended, but is not very DRY.

{% macro mobileNav(navLink1, navTitle1, options={}) %}

{% import _self as self %}

  {% set options = {
    navLink2: null,
    navTitle2: null,
    navLink3: null,
    navTitle3: null,
    navClass: '',
    navItemClass: ''

  }| merge(options) %}

      {% if navLink1 | length %}

          {{ navTitle1 }}

      {% endif %}

      {% if options.navLink2 | length %}

          {{ options.navTitle2 }}

      {% endif %}

      {% if options.navLink3 | length %}

          {{ options.navTitle3 }}

      {% endif %}

{% endmacro %}

I would like to DRY it out and have one list element where the number associated with the parameter dynamically increases.

Something like this (with the flexibility to an argument being passed via options as well):

 {% if navLink(a number between 1 & 3 that is passed in) | length %}

          {{ navTitle(a number between 1 & 3 that is passed in) }}

      {% endif %}

I haven't been able to figure out how to make it work though. Any help would be appreciated. Thanks!

Why don't you pass an array as a parameter?

{% macro mobileNav([
    {url: '/1', title: 'Foo'},
    {url: '/2', title: 'Bar'},
    {url: '/3', title: 'FooBar'},
], {} ) %}

And in your macro..

{% for item in items %}
    {% if item.title is defined and item.title is not empty and item.url is defined and item.title is not empty %}
         // ... output something
         {{ item.title }}
         {{ items|length <= 3? 'less than 4' : 'more than 3 are passed' }}
    {% endif %}
{% endfor %}


Image Optimize Field - adding ImOp field to a volume causes images in that volume to not be found Steps I've taken to configure Image Optimize

Installed plugin, configured binaries (green checkmarks all around)
from the CLI, ran ./craft resave/assets - all assets resaved and successful example: - Resaving Female (474749) ... done
created new OptimizedImages field "Optimized Images Field (Square)"
assigned this field to the Asset Volume Field Layout for our site content
from the CLI, ran ./craft resave/assets- all assets from that volume now are unable to be found
- Resaving Female (474749) ... error: The file "female.jpg" does not exist.

similarly, the CLI command for the plugin to run variants breaks the same way:

running ./craft image-optimize/optimize/create results in:

196/213 - processing asset: Female from field: Optimized Images Field (square)
[error]: The file "female.jpg" does not exist. while processing 196/213 - processing asset: Female from field: Optimized Images Field (square)

We've cleared caches, tried on fresh volumes, etc... same results whenever we add the Optimize Image Field to the volume.

We are still able to create front-end variants in twig, but none using the ImOp field.

  Craft CMS 3.4.15
  Image Optimize 1.6.12

Any recommendations on where to go from here?  Thanks in advance for any help.

Worked with @andrew.welch and found that, although our site is using /html for the webroot, there also existed a /web folder.  For a reason not yet identified, the plugin brought the /web folder to the surface as it was attempting to look in that folder.  I simply deleted the /web folder, and everything works.

The file craftcms/cms/src/console/Request.php sets the path based on what folders it finds on the filesystem, and "web" is before "html" in the array that it checks

    foreach (['web', 'public', 'public_html', 'html'] as $folder) {
        if (is_dir($dir . DIRECTORY_SEPARATOR . $folder)) {
            $dir .= DIRECTORY_SEPARATOR . $folder;
            break;
        }
    }

Thank you Andrew!


Integrating and Caching Weather Data from Forecast.io API Does anyone have any experience with integrating the forecast.io API for  location data for a Craft CMS site? I haven't been able to find any direct plugins for Forecast.io, but I was investigating the REST plugin as a possible option and I've also heard about FeedMe as well. Are there any preferred options as a best practice? My hope would be to be able to pull the data in and use it within a field of an existing entries page based on data on that entries page.

On a related note does wrapping Craft's caching tag around these plugin calls cache plugin output too? Probably a stupid question, just wanting to make sure I approach this solution correctly.

Looks like there are already several PHP libraries for the forecast.io API.

I'd probably spend a few minutes reviewing those and find one that's to your liking.  Then, it's a simple as writing a Craft plugin that utilizes that library to make calls to their API and deal with the response as appropriate.


Have some categories NOT linked to a category entry So my client has thrown a curve ball!  I've set-up a list of categories for the types of work they cover.  However, they DON'T want all of the categories to actually link to an entry.  In other words, they don't have content for some of the category pages, they would still like to SHOW the category on the front end but not have it clickable.

So, some category links are clickable, others not :/

Any ideas?

Thanks

Martin

I think I might have found a solution, although it might not be very elegant :/

So, i'm basically looking to see if a category field has content and then taking out the anchor in the template.

{% if category.practiceIntroText|length %}

{% endif %}
{{ category.title }}
{% if category.practiceIntroText|length %}

{% endif %}

Same code but making use of the ternary operator:

{% set catWithContent = category.practiceIntroText|length %}

{{ catWithContent ? '' }}
{{ category.title }}
{{ catWithContent ? '' }}


Is there a way to get the URL of the localised version of a product variant? I have a website that uses Craft Commerce and I'm trying to add a language menu that points to the localised version of each product variant as follows:

  {% set variantID = craft.request.getParam('variant') %}
  {% set locales = craft.i18n.getSiteLocales() %}

  {% for locale in locales %}
     {% set localisedEntryUrl = craft.commerce.variants.id(variantID).locale(locale.id).first().url() %}
     {{ localisedEntryUrl }}
  {% endfor %}

The problem is that the code above always produces the variant url for one language. eg.

/en/shop/ornaments/melisa?variant=9356
/en/shop/ornaments/melisa?variant=9356
/en/shop/ornaments/melisa?variant=9356

whereas I would expect something like:

/en/shop/ornaments/melisa?variant=9356
/de/shop/ornaments/melisa?variant=9356
/es/shop/ornaments/melisa?variant=9356

What am I doing wrong?

Try using this code:

{% set variantID = craft.request.getParam('variant') %}
{% set locales = craft.i18n.getSiteLocaleIds() %}

{% for locale in locales %}
    {% if variantID is defined %}
        {% set localisedEntryUrl = craft.commerce.variants.id(variantID).locale(locale).first %}
        {% if localeEntry.locale == locale %}
            {{ localisedEntryUrl.getUrl() }}
        {% endif %}
    {% endif %}
{% endfor %}


ElementAPI: How to order and/or limit results? Currently collaborating on a site with another developer, which is using ElementAPI pretty heavily for content delivery.

Is there a way to limit the number of returns on any given json feed? Say; only return the 10 most recent entries in any given channel? Or order the returned data by a specified field asc/desc?

A sample code:

'trucks.json' => [
  'elementType' => 'Entry',
  'criteria' => ['section' => 'trucks'],
  'paginate' => false,
  'transformer' => function(EntryModel $entry) {
    return [
      (int)$entry->id,
      $entry->manufacturer,

Just setting the limit property doesn’t do the trick alone, you need to deactivate pagination, too:

'criteria' => [
    'section' => 'trucks',
    'limit'   => 10,
    'orderBy'   => 'title asc',
],
'paginate' => false,


Product price format in euro I have a Craft/Commerce set up with Euro is base (and only) currency and 3 locales are defined in the site (nl_be, fr_be and en_be).

Prices are showing up as:

  0,99 €

instead of

  €0,99

When I print the entry's locale I get nl_be and my preferred language in the CP is also set to nl_be.

The url I'm using is also localised, through /nl/index.php, which sets CRAFT_LOCALE to nl_be.

I'm a bit clueless as to what I'm missing, any help would be appreciated.

Thanks!

Yii 1 gets its localization data from the Unicode Common Locale Data Repository.  You can see that info in craft/app/vendor/yiisoft/yii/framework/i18n/data/nl_be.php where currencyFormat is defined as 'currencyFormat' => '#,##0.00 ¤'.

¤ is the placeholder for the locale's currency symbol, which puts it after the digits, which explains the behavior you're seeing.

If you want to continue to use that specific locale, you could do a |replace everywhere you output a currency.  Or you could core hack that locale file to alter it and just make a note to check it after updating.  Those locale files do get updated, but it's pretty rarely. Or you could switch to nl.php which appears to have the currency symbol first.


Why isn't Craft displaying my plugin's changelog details? I can't figure out why Craft won't display my plugin's changelog details as expandable version headers, like it does for other plugins. I assume there's something wrong with the formatting in my CHANGELOG.md file, but I can't spot it.

The below screenshot is how my CHANGELOG.md renders inside Craft's update utility – notice that the version headers aren't expandable, which means there's no way to actually read the details for each version update:

The raw CHANGELOG markdown can be found here: https://raw.githubusercontent.com/mmikkel/Retcon-Craft/master/CHANGELOG.md

The changelogUrl attribute in the plugin's composer.json file is correct.

It looks like you have some en dashes – instead of hyphens - in your CHANGELOG.md version headings. These are probably causing some parsing issues.

Notice how there’s also no release date shown in the update utility.


Why can't I drag and drop fields in settings on a mobile phone? Each field has no option to move them on a phone. Using Firefox and Chrome on a Samsung Galaxy 5.

Touch screen devices don't "drag & drop" in a traditional sense, because dragging your finger around the screen is generally reserved for scrolling. This issue isn't specific to your browser or device, it's the same behavior across all touch screen devices.

Depending on how you want to look at this, I'd consider this either a "bug" or a "feature request". Assuming we're going with "feature request", your best course of action is to formally submit your request here:

  http://feedback.buildwithcraft.com/


"Template Not Found" error when trying to access a module controller action I'm a total Craft newbie, so I hope this question isn't ridiculous.

I just want to see a controller / action work in my new module.

I have src/controllers/ScrapeController.php as such:

<?php

namespace mycompany\mymodule\controllers;

use craft\web\Controller;

class ScrapeController extends Controller {

    public function actionPush()
    {
        return $this->asJson([
            'success' => TRUE,
        ]);
    }
}

And I just want to see this URL work: http://localhost/my-module/scrape/push

But instead I get: HTTP 404 - Template not found

I'm sure I'm missing something really dumb here. Any ideas?

You'll either need to use the action url http://localhost/actions/my-module/scrape/push since only those will route to controllers by default or create a custom route to your controller