Commerce new order error : mail::getRenderLanguage() must be of the type string I just pushed an update to the latest version of craft cms and craft commerce and ran into an error that is blocking new orders from finalizing.
Everything works on the local site. On the live site, attempting to place a new order throws a 500 error and doesn't complete the order or send a confirmation email. The payment, however, does go through.
In the web.log I can only find this error:
2021-01-17 18:00:08 [-][5709][d3ac37ae1b5d01a8535b021ef5e5a0b0][error][TypeError] TypeError: Return value of craft\commerce\models\Email::getRenderLanguage() must be of the type string, null returned in /home/okaytype/craft/vendor/craftcms/commerce/src/models/Email.php:117
Stack trace:
#0 /home/okaytype/craft/vendor/craftcms/commerce/src/services/OrderStatuses.php(440): craft\commerce\models\Email->getRenderLanguage(Object(craft\commerce\elements\Order))
#1 /home/okaytype/craft/vendor/craftcms/commerce/src/services/OrderHistories.php(127): craft\commerce\services\OrderStatuses->statusChangeHandler(Object(craft\commerce\elements\Order), Object(craft\commerce\models\OrderHistory))
#2 /home/okaytype/craft/vendor/craftcms/commerce/src/elements/Order.php(1971): craft\commerce\services\OrderHistories->createOrderHistoryFromOrder(Object(craft\commerce\elements\Order), NULL)
#3 /home/okaytype/craft/vendor/craftcms/cms/src/services/Elements.php(2454): craft\commerce\elements\Order->afterSave(false)
#4 /home/okaytype/craft/vendor/craftcms/cms/src/services/Elements.php(755): craft\services\Elements->_saveElementInternal(Object(craft\commerce\elements\Order), false, false, true)
#5 /home/okaytype/craft/vendor/craftcms/commerce/src/elements/Order.php(1576): craft\services\Elements->saveElement(Object(craft\commerce\elements\Order), false)
#6 /home/okaytype/craft/vendor/craftcms/commerce/src/controllers/OrdersController.php(221): craft\commerce\elements\Order->markAsComplete()
#7 [internal function]: craft\commerce\controllers\OrdersController->actionSave()
#8 /home/okaytype/craft/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array(Array, Array)
#9 /home/okaytype/craft/vendor/yiisoft/yii2/base/Controller.php(180): yii\base\InlineAction->runWithParams(Array)
#10 /home/okaytype/craft/vendor/craftcms/cms/src/web/Controller.php(190): yii\base\Controller->runAction('save', Array)
#11 /home/okaytype/craft/vendor/yiisoft/yii2/base/Module.php(528): craft\web\Controller->runAction('save', Array)
#12 /home/okaytype/craft/vendor/craftcms/cms/src/web/Application.php(274): yii\base\Module->runAction('commerce/orders...', Array)
#13 /home/okaytype/craft/vendor/craftcms/cms/src/web/Application.php(577): craft\web\Application->runAction('commerce/orders...', Array)
#14 /home/okaytype/craft/vendor/craftcms/cms/src/web/Application.php(253): craft\web\Application->_processActionRequest(Object(craft\web\Request))
#15 /home/okaytype/craft/vendor/yiisoft/yii2/base/Application.php(386): craft\web\Application->handleRequest(Object(craft\web\Request))
#16 /home/okaytype/craft/web/index.php(42): yii\base\Application->run()
#17 {main}
2021-01-17 18:00:07 [-][5709][d3ac37ae1b5d01a8535b021ef5e5a0b0][info][application] $_GET = [
    'p' => 'adminbuttstuff/commerce/orders/39536'
]

It seems like Craft is looking for a language value of some kind but I can't figure out where or how to provide it.
I've tried editing the settings in Commerce > System Settings > Email > Language to English, but it always reverts to "The language the order was made.", which is also English.
Update: I can get an order to finalize if I turn off the email confirmation. This makes me think there is a problem with the email template, but I'm not getting a system error not a twig error. My email template doesn't use a $language variable anywhere.
Any help would be hugely appreciated. Thanks.

I think I figured out the problem. This was my first time switching to the project.yaml configuration Deleting and rebuilding the project config allowed me to change the Commerce > System Settings > Email > Language which fixed the error.


Error using assets operations I am having trouble getting images by name. craft.assets.first() function in assets gives the proper output of one image.

But when I try craft.assets.filename('flag.jpg'), craft shows the following error:

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

Same with other functions of assets. Please help me solve this error.

Thank You.

Please read the docs about ElementCriteriaModel craft.assets returns you an element of type ElementCriteriaModel so you can define criteria for your search. In order to fetch the elements you have to do first(), find(), last() or certain other functions.

craft.assets.filename('flag.jpg').first()


Stop window refreshing in Live Preview? I am working on LivePreview and the window it's get loaded at every change. It is possible to do that only when I will click the Save button?

No, that’s the whole point of Live Preview, to update and preview the changes “live”.

If that’s not what you want you can save the entry via “Save an continue editing” (keyboard shortcut CMD+S) and then view the changes by clicking the “Entry link” button.


Encoding special characters even with the raw filter due to include Hey guys i have something odd happening and I don't understand why:

The opening of my template i set a variable {% set text = component.textarea ?? null %}

Lower in my template i have the following: {% set text = include('_components/_dataTypes/textarea') %}

That template only currently has {{ text }} in it so as of right now doesn't mean much.

Then last in my template i have {{ text|raw }}

However characters are still encoded.

I've found that if i remove the include template, even though all it includes is {{ text }} that |raw works. I should note that if i put |raw in the include template, it still does not work.

Why is that? Is it a parse order thing or what's going on there that causes the include to ignore the filter? I should note that using Wordsmith and the |pde filter does work regardless of the include... however characters such as < > ' " etc. are still encoded, where as they are not without the include.

Please help me understand why this is occurring. Thank you.

As mentioned in the Discord you are probably looking for the source function.

The reason the include doesn't work is covered in the old PR for (what eventually became) source. It's probably best I link all that discussion than try to put it in my own words here!

Initial discussion with your problem
First PR
Further PR after discussion (the source function as it is now)


Display entries with matching checkbox field values I apologize if this question has been asked before. I'm new at this and am struggling to figure out if what I need to do is possible/the right way to do it or if I need to structure my content differently.

My entries in a section have a field that use a checkbox field type. I would like to display entries that have a matching value based on that field.

Example:
 Field: Vitamins,

  Field Type: Checkboxes
              Option: Vitamin A  | Value: a
              Option: Vitamin B  | Value: b
              Option: Vitamin C  | Value: c

Section: Vegetables

 -Entry: Broccoli
       Vitamins Field Values: a, c

 -Entry: Corn
       Vitamins Field Values: a, b

 -Entry: Squash
       Vitamins Field Values: a, b, c

I'm trying to figure out how to display all entries that contain Vitamin A.

After I posted my question I ended up coming with something that works:

 {% for entry in craft.entries.section('Vegetables') if entry.Vitamins.contains('a') %}

{{ entry.title }}

 {% endfor %}


Translate Section name I can see in the CP (craft 3) that my sections have a 'translatable' icon but I don't find anywhere in the UI to translate section names.

What's the best way to translate these?

I haven't found how to do it through the UI but it's possible to add the section names in translation files as keys and then translate them in the views using {{ "key_name" | translate }}.

You must follow this example but keeping in mind the translations folder changed its location and structure from Craft 2 to Craft 3.

You have to place it right under your project directory:

yourProject
|--templates
|--translations/
|---en/
|-----site.php
|---es/
|-----site.php
|--vendor


What does the Timezone in Settings -> General represent? Should it be set to the timezone of the server Craft is installed on, or the timezone of the current user, or something else?

I can find no documentation about these settings anywhere.

You set it to whatever timezone the content authors will be in, so for example, when they say an entry’s post date is at 10 AM, Craft knows which timezone that should refer to.


Where can I set how the pagination links render? I have inherited a Craft 3 project in which the pagination links render with a query parameter "page": https://mysite.com/blog/?page=2 but this makes crawlers like HREFS to ignore the Next and Prev links (resulting in over 100 "orphan" pages).
Where can I reset my pagination links to the standard https://mysite.com/blog/p2 format?

Delete the overridden pageTrigger config setting in your config/general.php file:
https://docs.craftcms.com/v3/config/config-settings.html#pagetrigger


'If/else' statement inside 'nav' tag Craft CMS V2.
Comment Plugin: verbb comment

    {% nav comment in comments %}
       {% if comment.isFlagged() == false %}

              {% include '_forms/templates/comment-' ~ comment.status %}
              {% include '_forms/templates/form' %}

            {% ifchildren %}

                    {% children %}

            {% endifchildren %}

       {% endif %}
    {% endnav %}

The above code creates this error:

Unexpected "ifchildren" tag (expecting closing tag for the "if" tag)

So, How can I use if/else condition inside the nav tag to hide flagged comment including it's children.

Short answer, it can't be done. I'm not sure why, but it's some sort of conflict with how nav, children, and ifchildren operates.

The workaround is ugly (but it works). Just use two separate, but identical if statements... one before the ifchildren, and one after.

{% if comment.isFlagged() == false %}
    ...
{% endif %}
{% ifchildren %}
    ...
{% endifchildren %}
{% if comment.isFlagged() == false %}
    ...
{% endif %}

EDIT:

If this solution doesn't work for you, I recommend looping over the comments array and removing all flagged comments before you run it through the nav loop.


Strange Link Problem I am creating a blog with an index page that links to individual blog show pages. I'm having a weird issue where when I click on the title on the index page instead of it linking to: my_current_website.com/blog/blog_post_title it is linking to: my_live_website.com/blog/blog_post_title, which doesn't even exist. Any thoughts on why this would occur?
In the template I am setting up the link with entry.url.

The cause of this issue with a 90% likelyhood are your craft settings

Before you try any of the below steps, try clearing your cache first!

Sometimes some leftover cache is all that needs to be removed to fix an issue...
rm -rf runtime/* or ./craft clear-caches/all

3 Settings which you may have set wrongly:

All of the below mentioned settings should basically be pointing towards my_current_website.com, a reference to that or something more relative like a simple /.

There are 3 Places where you should check if you have my_live_website.com set as your current host/site.

.env's SITE_URL, BASE_URL or anything else that has  SITE or URL in it's name
config/general.php's siteUrl Value(s)
Your Craft Control Panel Settings, my_current_website.com/admin/settings/sites (URL may differ based on config/general.php's cpTrigger value)


Related Entries to Users I'm currently doing the following query, it's working nicely on my local environment but on Production it's allowing all users to see all entries which is really strange? I can't see anything wrong with my code that would be causing this to break?

{% set campaigns = craft.entries.section('campaigns').authorId(currentUser.id).all() %}
{% set proposals = craft.entries.section('proposals').relatedTo(campaigns).all() %}
{% set proposalsByGroup = proposals|group('proposalStatus') %}

If currentUser isn't defined, it returns null. So what's probably happening is you have people visiting the site who don't have user accounts or aren't signed in, which means the currentUser variable is set to null for them. So in your query you end up passing null to the authorId param, which means it will get everything (null being the default if I'm not mistaken). Most likely in your local environment you did all your testing while being signed in.

To solve, you'll want to surround your code in a conditional:

{% if currentUser %}
    {% set campaigns = craft.entries.section('campaigns').authorId(currentUser.id).all() %}
    {% set proposals = craft.entries.section('proposals').relatedTo(campaigns).all() %}
    {% set proposalsByGroup = proposals|group('proposalStatus') %}
{% else %}
    Please sign in to view your proposals...
{% endif %}


CP not loading on Forge Server with PHP 7 I uploaded a working install of Craft Pro 2.5.2754 to a brand new Laravel Forge server and I'm having issues with the control panel. More precisely, it returns an error 500 when I try to access it.

The PHP version is PHP 7.0.0-4+deb.sury.org~trusty+1 and it's the default config of Forge.

I have a config array in craft/config/general.php that looks like this :

$data['dev.domain.com']  =   [
    'appId'                 => 'choiStage',
    //'cacheMethod'           => 'memcache',
    'devMode'               => true,
    'phpMaxMemoryLimit'     => '512M',
    'cpTrigger'             => 'craft',

    'backupDbOnUpdate'      => true,
    'usePathInfo'           => true,
    'omitScriptNameInUrls'  => true,
    'enableCsrfProtection'  => false,
];
return $data;

When I access the control panel located at /craft I get an error 500.

When I have a look at craft/storage/runtime/log/craft.log there is this message :

    ******************************************************************************************************
2015/12/09 15:42:38 [error] [exception.Error] Error: Class 'Twig_Cache_Filesystem' not found in /home/forge/staging.domain.com/releases/20151209154140/craft/app/vendor/twig/twig/lib/Twig/Environment.php:263
Stack trace:
#0 /home/forge/staging.domain.com/releases/20151209154140/craft/app/vendor/twig/twig/lib/Twig/Environment.php(115): Twig_Environment->setCache('/home/forge/cho...')
#1 /home/forge/staging.domain.com/releases/20151209154140/craft/app/services/TemplatesService.php(147): Twig_Environment->__construct(Object(Craft\TemplateLoader), Array)
#2 /home/forge/staging.domain.com/releases/20151209154140/craft/app/services/TemplatesService.php(221): Craft\TemplatesService->getTwig()
#3 /home/forge/staging.domain.com/releases/20151209154140/craft/app/controllers/BaseController.php(74): Craft\TemplatesService->render('login', Array)
#4 /home/forge/staging.domain.com/releases/20151209154140/craft/app/controllers/TemplatesController.php(55): Craft\BaseController->renderTemplate('login', Array)
#5 [internal function]: Craft\TemplatesController->actionRender('login', Array)
#6 /home/forge/staging.domain.com/releases/20151209154140/craft/app/framework/web/actions/CAction.php(109): ReflectionMethod->invokeArgs(Object(Craft\TemplatesController), Array)
#7 /home/forge/staging.domain.com/releases/20151209154140/craft/app/framework/web/actions/CInlineAction.php(47): CAction->runWithParamsInternal(Object(Craft\TemplatesController), Object(ReflectionMethod), Array)
#8 /home/forge/staging.domain.com/releases/20151209154140/craft/app/framework/web/CController.php(308): CInlineAction->runWithParams(Array)
#9 /home/forge/staging.domain.com/releases/20151209154140/craft/app/framework/web/CController.php(286): CController->runAction(Object(CInlineAction))
#10 /home/forge/staging.domain.com/releases/20151209154140/craft/app/framework/web/CController.php(265): CController->runActionWithFilters(Object(CInlineAction), Array)
#11 /home/forge/staging.domain.com/releases/20151209154140/craft/app/framework/web/CWebApplication.php(282): CController->run('render')
#12 /home/forge/staging.domain.com/releases/20151209154140/craft/app/framework/web/CWebApplication.php(141): CWebApplication->runController('templates/rende...')
#13 /home/forge/staging.domain.com/releases/20151209154140/craft/app/etc/web/WebApp.php(284): CWebApplication->processRequest()
#14 /home/forge/staging.domain.com/releases/20151209154140/craft/app/framework/base/CApplication.php(184): Craft\WebApp->processRequest()
#15 /home/forge/staging.domain.com/releases/20151209154140/craft/app/index.php(62): CApplication->run()
#16 /home/forge/staging.domain.com/releases/20151209154140/public/index.php(19): require_once('/home/forge/cho...')
#17 {main}
REQUEST_URI=/craft/login
---

I tried various cacheMethod without any luck and now I'm kinda stuck.

2015/12/09 15:42:38 [error] [exception.Error] Error: Class 'Twig_Cache_Filesystem' not found in /home/forge/staging.domain.com/releases/20151209154140/craft/app/vendor/twig/twig/lib/Twig/Environment.php:263

That indicates that Craft is missing some of its files.  Try re-uploading your craft/app folder with a fresh copy downloaded from https://craftcms.com.


Change email address on front end Some similar posts on here already but I'm still struggling. My code looks fine as far as I can tell? Page just reloads with no changes to the email (other fields change fine). I'm missing something right?

<form method="post" accept-charset="UTF-8" enctype="multipart/form-data" class="js-validate">
{{ getCsrfInput() }}
<input type="hidden" name="action" value="users/saveUser">
<input type="hidden" name="redirect" value="{{ craft.request.url ~ '/saved' }}">
<input type="hidden" name="userId" value="{{ currentUser.id }}">
<input type="hidden" name="password" value="{{ currentUser.password }}">

{{ "My Profile"|translate }}

        {{ "First Name"|translate }}*
        <input type="text" name="firstName" id="firstName" placeholder="{{ "First Name"|translate }}" value="{{ currentUser.firstName }}" required>

        {{ "Last Name"|translate }}*
        <input type="text" name="lastName" id="lastName" placeholder="{{ "Last Name"|translate }}" value="{{ currentUser.lastName }}" required>

        {% if currentUser.unverifiedEmail %}

{{ "Email verification pending"|translate }}

{{ "We sent a verification email to"|translate }} {{ currentUser.unverifiedEmail }}. {{ "Until this email is verified, we’ll continue to use your previous email"|translate }} ({{ currentUser.email }}).

        {% else %}
            Email*
            <input type="email" name="email" id="email" placeholder="{{ "Email"|translate }}" value="{{ currentUser.email }}" required>
        {% endif %}

        {{ "Town/City"|translate }}
        <input type="text" name="fields[userTownCity]" id="userTownCity" placeholder="{{ "Town/City"|translate }}" value="{{ currentUser.userTownCity }}">

        {{ "Phone Number"|translate }}
        <input type="text" name="fields[userPhoneNumber]" id="userPhoneNumber" placeholder="{{ "Phone Number"|translate }}" value="{{ currentUser.userPhoneNumber }}">

<input type="submit" value="Save Changes" class="button button--fw">

Thanks to billythekid's suggestion, adding a password field creates an elevated session, and solves my problem.

<input type="password" name="password" placeholder="Password" required>

Actually I don't think it's that intrusive, and it's a good security step that should generally be encouraged when making any profile edits.


Adding a postDate with Guest Entries Is it possible to set the postDate for a new (disabled) entry created using the GuestEntries plugin?

Otherwise when posting a GuestEntry the postDate is not set until the entry is enabled or re-saved from Craft.

Posting this with an answer as it may be useful to other people. If there are better ways to do this please add them.

You can add a hidden field for your postDate to your GuestEntry form, e.g.

<input type="hidden" name="postDate" value="{{ now|date("Y-m-j H:i:s") }}" />

This adds the postDate using Craft's YYYY-MM-DD HH:MM:SS format.


Element API: Get Matrix Content So I'm trying to get my Matrix as JSON with the Craft CMS Element API plugin.

<?php

use Craft\elements\Entry;

return [
    'endpoints' => [
        'api/sites' => [
            'elementType' => craft\elements\Entry::class,
            'criteria' => ['section' => 'sites'],
            'elementsPerPage' => 1,
            'transformer' => function(Entry $entry) {
                $matrixBlocks =[];
                foreach ($entry->contentMatrix as $block) {
                    switch ($block->type->handle) {
                        case 'sectionTitleBlock':
                            $matrixBlocks[] = [
                                'content' => $block->sectionTitleBlock
                            ];
                            break;
                    }
                }
                return [
                    'matrix' => $matrixBlocks,
                ];
            },
            'paginate' => false,
            'pretty' => true,
        ],
    ]
];

The error message im getting is

  "error": {
      "code": 2,
      "message": "Invalid argument supplied for foreach()"
    }

I think the problem is that $entry->contentMatrix is giving me a MatrixBlockQuery Element.

$sectionTitleBlock is a normal text field

In order to get all related items from a BaseRelationField you'll need this syntax

$entry->getFieldValue('contentMatrix')->all()

Thus your loop will be

foreach($entry->getFieldValue('contentMatrix')->all() as $block){


Sprout Forms: Populate checkbox field options with entry data I have a form with a checkbox field. I want the options of the checkbox to be pulled from an entry field.

My custom field template is below but it wont pass validation. I guess this is because Sprout looks for the option values to validate but as they are populated from an entry it wont pass??

At the moment the example below is successfully displaying the entry data as options in the checkbox, it just wont allow me to submit the form.

{% if handle == "checkboxes1" %}

        <div
                {%- if id %} id="{{ id }}"{% endif %}
                {%- if class %} class="{{ class }}"{% endif %}>

            {% if name is defined and (name|length < 3 or name|slice(-2) != '[]') %}
                <input type="hidden" aria-hidden="true" name="{{ name }}" value="">
            {% endif %}

                {% for date in entry.eventOccurrences %}

                <label for="checkboxes1-{{ loop.index }}">

                        <input type="checkbox"
                        data-value="{{ date.date }}"
                                {%- if name %} name="checkboxes1"{% endif %}
                                {%- if id %} id="checkboxes1-{{ loop.index }}"{% endif %}
                                {%- if value %} value="value-{{ loop.index }}"{% endif %}
                        >

                        &nbsp;{{ date.date }}||

                </label>

            {% endfor %}
        </div>

{% endif %}

The best way to debug a form field using custom HTML is to output the field you want via the default displayForm tag and copy the code from there as a starting point:

{# Output your checkboxes field here and look at the code generated #}
{{ craft.sproutForms.displayForm('yourFormWithACheckbox') }}

Test with the default code that is output as your custom HTML and if that works, adjust from there.

In general, we recommend using custom HTML with caution as it can increase the complexity of the code on the front-end a great deal.


Craft 2: Suspend user results in "Unauthorized You don’t have the proper credentials to access this page." This pertains to a Craft v2.9.2 installation.
User X is an admin user. So she has permission for pretty much everything, except accessing site settings, etc.
For an unknown reason, User X is unable to suspend other users.
User X has all permissions assignable under General and Users on the Permissions tab.
Yet when she tries to suspend another user, Craft returns the following error:
Unauthorized
You don’t have the proper credentials to access this page.

I have no idea why. Is there something I am over-looking regarding what's required for a user to suspect another user?
Is there a way to find out what is causing this issue? Such as a log of such issues?
Thank you.

Is she trying to suspend another user who's an admin user?
I just tested this and your scenario would happen if she's trying to suspend an Admin's account.
A user who's has Admin privileges can only suspend another Admin otherwise you'd have users with lower-level permissions overriding those with higher level ones.
In Craft 3, you get a more clear message if this happens:


Templating for Structures I can't find anything in the Craft 3 docs that explains templating for a structure entry. What I want to do is show level 1 entries with their associated level 2 entries in a simple list type organization.

I was able to do that with Craft 2 by using {% set subItems = entry.children %} where entry was set to level 1 entries, but that does not work.

I can't figure out how to associate levels with parents/children. Am I missing something in the docs? Thanks for any help!

Nevermind - had a typo in my template code. Using "descendantOf" works as advertised!


Securing a Generated PDF I recently purchased the Digital Download plugin for Craft.

I'm wanting to secure a PDF download generated by another plugin called Enupal Snapshot. Reviewing the Digital Download documentation I'm not entirely sure how I would do that using the following code which generates the PDF on the fly?

Update 1

Advice has been given that we need to provide the file path. In order to get the file path in Enupal Snapshot you need to return the asset model of the PDF.

Update 2

The code was changed to reflect asset model requirment. Unfortunatly I get a "Impossible to invoke a method ("getPath") on a string variable" highlighting {% set filePath = assetModel.getPath() %} in the code.

Code

{% set pdfName = 'now'|date('Y-m-d') ~ '-' ~ date().timestamp ~ '-evaluation-' ~ companyName ~ '-' ~ firstName ~ '-' ~ lastName ~ '-' ~ submissionId ~ random(50, 500) ~ '.pdf' %}

{% set assetFolderRef = evaluationSettings.evaluationAssetRef %}
{%
    set settings = {
        filename: pdfName,
        inline: false,
        overrideFile: true,
        asModel: true,
        singleUploadLocationSource: assetFolderRef,
        cliOptions: {
            'header-html': 'evaluation-tools/evaluation/pdf-header',
            'footer-html': 'evaluation-tools/evaluation/pdf-footer',
            'orientation': 'Portrait',
            'page-size': 'A4',
            'title': 'Evaluation for ' ~ companyName,
        },
        variables: {
            passSubmissionId: submissionId,
        }
    }
%}

{% set assetModel = craft.enupalsnapshot.displayTemplate("evaluation-tools/evaluation/pdf-report", settings) %}
{% set token = craft.digitalDownload.createToken(assetModel, options) %}

     Download Report

Following the Digital download docs you may need the file path, so in order to get the file path in Enupal Snapshot you may need to return the asset model of the PDF:

{%  set settings = {
        filename: 'my-first-pdf.pdf',
        inline: false,
        asModel: true
    }
%}

{% set assetModel = craft.enupalsnapshot.displayTemplate("reports/pdf-report", settings) %}

{# Digital Download code #}
{% set token = craft.digitalDownload.createToken(assetModel, options) %}

{{ assetModel.filename}}


Grabbing the existing address data to use with Smart Map I'm new to Craft CMS, so pardon me. I've been using the VZ Address plugin to handle all our address entries, and have a couple hundred of workshop address entries already.
I'm trying to use Smart Map to generate a map, search by zip code, for the workshop addresses that are already been created with VZ Address. How can I grab that info from VZ Address field and use it with Smart Map?
Thank you for any help!

I'd recommend migrating all of your map data into a Smart Map Address field. Once you've got everything contained within Smart Map, it will be much easier to render maps and conduct proximity searches.

The best way to migrate would be to use something like Feed Me...

Create a simple JSON or RSS feed which contains only (A) the entry ID, and (B) the VZ Address data.
Pull that feed right back into the same site, putting the address data into your Smart Map field.

Once you’ve migrated to Smart Map, it opens up a lot more possibilities for using that data!


Asset thumbs missing in control panel after Assets Source update I've updated several Assets Sources on my production site. I've exported / imported the database from production into local - the new Assets Sources are in place but the asset thumbs are now missing.

How can I get Craft to re-generate these please?

Go to Settings > Clear Caches. Should regenerate them all from the new source.


Removing the LivePreview and Share Buttons? Is there a way to deactivate this functionality? We dont want our clients to use it just yet.

I could delete them with my Module's js, but it is triggered after the site is build and the "popping" away of the buttons is not really pretty.

If you add a blank or invalid template path in your Section's settings (Settings > Sections > Edit Section) then both live preview and the share button will be disabled.


Update entry title for all sites I'm working on a Craft project that has 3 sites. The content for one section is pulled from an API using a console script which runs every 5 minutes.
This has been working fine but I've discovered a bug that the title's aren't being updated across all sites as they are translatable.
This is my current code.
$entry->title = $data->name;
$entry->setFieldValues([
    'body' => $data->text,
    'relatedArticles' => array_map(function($id){
        return [
            'relatedId' => $id,
        ];
    }, $data->related),
    'categories' => array_map(function($cat) {
        return (isset($this->categories[$cat])) ? (int) $this->categories[$cat] : false;
    }, $data->categories),
]);
$success = Craft::$app->elements->saveElement($entry);

All other fields are not translatable so they work fine, Is there a way to propagate the title across all sites or do I need to loop through all the sites to update the entry?

Assuming you're on the latest 3.5.x release, then my guess is you need to set the "Title Translation Method" setting for whatever Entry Type you're saving to to "Translate for each site".


Using relatedTo, and/or and :empty/:notempty in queries I got users that has 3 Entries fields in their profile: breadForMonday, breadForWednesday and breadForFriday.

I want to differentiate between users with 1, 2 or 3 selected entries. How would I use relatedTo together with and/or and :empty/:notempty?

Something like this:

{% set bread = craft.entries({ section: 'bread' }).limit(null) %}
{# Find users that have selected entries for two out of three fields #}
{% set users = craft.users({
    group: 'customers',
    relatedTo: [
        'and',
        { targetElement: bread, field: 'breadForMonday' },
        { targetElement: bread, field: 'breadForWednesday' }
    ]
}) %}

Please don't laugh, but I thought to myself, let's give this a go in Twig and see where it takes me.
It very soon began to become clear, that this will end up in lots of criteria models, db queries and a huge pile of Twig code.

So my better answer should be, don't do it in Twig. This is something you should better do in PHP with
custom database queries (→ Yii query builder). But now that I've done it, here's a gist of that Twig code.


Impossible to invoke a method ("getUrl") on a null variable I've a problem with this code. I get the error message:

  Impossible to invoke a method ("getUrl") on a null variable.

For this code:

{% if siteBgBlureFallback %}
    background-image: url({{ siteBgBlure.first().getUrl('bodyBg') }});
{% endif %}

Here is the full code:

{% if entry is defined %}
    {% set siteBg = entry.siteBg %}
    {% set siteBgBlure = entry.siteBgBlure %}
{% endif %}

{% set siteBgFallback = siteBgFallback.siteBg %}
{% set siteBgBlureFallback = siteBgFallback.siteBgBlure %}

.bg {
{% if siteBg is defined and siteBg is not empty %}
    {% if siteBg %}
        background-image: url({{ siteBg.first().getUrl('bodyBg') }});
    {% endif %}

{% else %}

    {% if siteBgFallback %}
        background-image: url({{ siteBgFallback.first().getUrl('bodyBg') }});
    {% endif %}
{% endif %}
}

.bgblure {
{% if siteBgBlure is defined and siteBgBlure is not empty %}
    {% if siteBgBlure %}
        background-image: url({{ siteBgBlure.first().getUrl('bodyBg') }});
    {% endif %}

{% else %}
    {% if siteBgBlureFallback %}
        background-image: url({{ siteBgBlureFallback.first().getUrl('bodyBg') }});
    {% endif %}
{% endif %}
}

I don't understand why the first three outputs work and the 4th won't work any more.

The backup fields have some pic in there.

Thx for your help :)

You can do it like this:

.bg{
    background-image: {{ entry.siteBg.first().getUrl('bodyBg')|default(siteBgFallback.siteBg.first().getUrl('bodyBg)}}
}

And the same for the other one. What you are doing is the following:

Set an item that can be empty (hence the |default).
If the item is empty go to the fallback (the part between the default brackets).

For more info on the default filter check here


How to make a multiple route? Can't figure out how to create a dynamic route for the categories in this format:

site.com/news/category-1-and-category-2-and-category-3

That would bring the results from these slug categories.

Trying to build a complex query and I'm sure there is bound to be a better way of doing it that.

'news/<categories:.*>/<categorySlugs:{slug}(\-and\-{slug})+>' => ['template' => 'news/index']

Have you tried processing the entire slug directly in your template, without setting a complex route? Check for the presence of the string "-and-", split the slug accordingly, build a Category query.


Internal server error message I'm getting the following internal server error message when I try and make a change on my website. It is only happening on one page!

file_get_contents(https://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=610+Bunker+Ave.+Kellogg%2C+Idaho+83837): failed to open stream: HTTP request failed! HTTP/1.0 403 Forbidden

I'm guessing you're using some sort of Google Maps plugin on your site. Google recently started limiting access to their Maps API, and now you need a key to be able to make Maps requests.

Go here to request an API key: https://developers.google.com/maps/documentation/javascript/get-api-key. Then input the key into whatever plugin is using Google Maps. There should be a field in the plugin settings that asks for the key.


Image transform in a plugin How can I trigger an image transform in a Craft plugin?

Yes, it's possible.

It essentially works just like it does in twig...you just call getURL with the valid name of a transform

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

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

$imgUrl = $image->getUrl('tranformHandle);

...as I understand it that triggers the  image to be transformed on-demand if the transform does not already exist.


How to include external JavaScript in place? We include an external script from a vendor and the URL doesn't end in .js. It returns JavaScript that creates a widget in place. I was able to fake it out by adding a '&js=.js' parameter but it still rendered with the other scripts.
Is there an option for {% js %} to render in place? A {% js at right-here %}?

In your template you can use the <script src=""> tag as it's a combination of the html and twig. So it will load your external javascript files.
Also you can use the inline javascript or javascript file using this tag {% js %} like below.
{# Use for JS file #}
{% js "/assets/js/script.js" %}

{# Use as a JS code block #}
{% js %}

console.log("hello World");

{% endjs %}


An unknown error occurred - no log entry After copying files from a web server to my local devbox I am unable to open any 'Entries'. I keep getting two of the following error: "An unknown error occured."

The assets section does open and I am able to see the various loaded assets.. This also does not display, same error pop-up.

The strangest part is there are no logs to speak of... I tried clearing all the logs just in case, but they're still empty.

I'm using Laragon with PHP 7.2.11 Apache 2.4.35 and two different sites give me the same error.

EDIT: I have tried ignore_user_abort = On in my php.ini file as per a similar issue

EDIT: The only php error is recurring on every page load, but I thought it was a compatibility thing:

[24-Apr-2019 08:08:02 UTC] PHP Warning:  Use of undefined constant auto - assumed 'auto' (this will throw an Error in a future version of PHP) in D:\laragon\www\cannon-kitchens\craft\config\general.php on line 13

EDIT: I am now seeing some logs, but this appears to be normal operation:

2019-04-24 10:13:58
Level   profile
Category    system.db.CDbCommand.query
Message     end:system.db.CDbCommand.query(SELECT `t`.`id` AS `t0_c0`, `t`.`structureId` AS `t0_c1`, `t`.`fieldLayoutId` AS `t0_c2`, `t`.`name` AS `t0_c3`, `t`.`handle` AS `t0_c4`, `t`.`hasUrls` AS `t0_c5`, `t`.`template` AS `t0_c6`, `t`.`dateCreated` AS `t0_c7`, `t`.`dateUpdated` AS `t0_c8`, `t`.`uid` AS `t0_c9`, `structure`.`id` AS `t1_c0`, `structure`.`maxLevels` AS `t1_c1`, `structure`.`dateCreated` AS `t1_c2`, `structure`.`dateUpdated` AS `t1_c3`, `structure`.`uid` AS `t1_c4` FROM `craft_categorygroups` `t` LEFT OUTER JOIN `craft_structures` `structure` ON (`t`.`structureId`=`structure`.`id`) ORDER BY name)
2019-04-24 10:13:58
Level   profile
Category    system.db.CDbCommand.query
Message     begin:system.db.CDbCommand.query(SELECT `t`.`id` AS `t0_c0`, `t`.`structureId` AS `t0_c1`, `t`.`fieldLayoutId` AS `t0_c2`, `t`.`name` AS `t0_c3`, `t`.`handle` AS `t0_c4`, `t`.`hasUrls` AS `t0_c5`, `t`.`template` AS `t0_c6`, `t`.`dateCreated` AS `t0_c7`, `t`.`dateUpdated` AS `t0_c8`, `t`.`uid` AS `t0_c9`, `structure`.`id` AS `t1_c0`, `structure`.`maxLevels` AS `t1_c1`, `structure`.`dateCreated` AS `t1_c2`, `structure`.`dateUpdated` AS `t1_c3`, `structure`.`uid` AS `t1_c4` FROM `craft_categorygroups` `t` LEFT OUTER JOIN `craft_structures` `structure` ON (`t`.`structureId`=`structure`.`id`) ORDER BY name)
2019-04-24 10:13:58
Level   trace
Category    system.db.CDbCommand
Message     Querying SQL: SELECT `t`.`id` AS `t0_c0`, `t`.`structureId` AS `t0_c1`, `t`.`fieldLayoutId` AS `t0_c2`, `t`.`name` AS `t0_c3`, `t`.`handle` AS `t0_c4`, `t`.`hasUrls` AS `t0_c5`, `t`.`template` AS `t0_c6`, `t`.`dateCreated` AS `t0_c7`, `t`.`dateUpdated` AS `t0_c8`, `t`.`uid` AS `t0_c9`, `structure`.`id` AS `t1_c0`, `structure`.`maxLevels` AS `t1_c1`, `structure`.`dateCreated` AS `t1_c2`, `structure`.`dateUpdated` AS `t1_c3`, `structure`.`uid` AS `t1_c4` FROM `craft_categorygroups` `t` LEFT OUTER JOIN `craft_structures` `structure` ON (`t`.`structureId`=`structure`.`id`) ORDER BY name
2019-04-24 10:13:58
Level   profile
Category    system.db.CDbCommand.query
Message     end:system.db.CDbCommand.query(SHOW CREATE TABLE `craft_structures`)

Clear your Cache manually going into the Storage folder. It happens when you add new entries and the code is not written properly or any other issue may reflect this error. So the best thing to clear the storage part manually.

To do this; Delete the entire folder \craft\storage\runtime


Can you get the HTTP status code in twig templates? I need a nice way to determine whether I'm on a 200 page. Basically anything other than a status page (404, 500, 403) in twig templates.

I thought I could do something like craft.request.getStatus or craft.request.status but this didn't work.

From looking in the HttpRequestService.php file there doesn't seem to be anything to retrieve this info so I wondered if anyone has achieved something similar.

Since this is the top hit in Google, I'll guess it's handy to mention that craft.app.response.statusCode will display the statuscode in Craft v3 and up.


Channel Section with individual entry template and index templates? I am looking for suggestion on how to setup a resource section on a site I'm building. Here is the structure.

Resources - Index

Entry type of resources
Webinars
-Webinar Entry (template for a single webinar)
-Webinar Index (all webinars)
Whitepapers
-Whitepaper Entry (template for a single whitepaper)
-Whitepaper Index (all whitepapers)
Ebooks
-Ebook Entry (template for a single ebook)
-Ebook Index (all ebooks)

I was originally thinking to this as a channel, but how to I create indexes for the entry types: webinars, whitepapers, and ebooks?

The way I've done this in previously is in your templates have a directory titled Resources and inside that directory another directory titled _types

Within the _types directory I will have the code to output the content based on the entry type. I would name each of those templates ENTRY-TYPE-HANDLE.html

The on your Resources index user the following:
{% include "resources/_types/" ~ entry.type %}


Search Contact Person Plugin via Ajax I'm new to Craft and I'm trying to achieve the following with a Craft Plugin

A user visits my site and can input a zip code to receive the corresponding contact person's name, phonenumber and image. I want to develop a plugin which allows the admin to create the contact person entries in the backend and which handles the ajax request by getting the right contact person form the database.

So for example, the user sends the zip code 54343, an ajax request with that data is sent, the plugin queries the database, converts the result into a json-string and sends the ajax response back.

I'm afraid I have no idea how to start.

How do I create the table and import the data? (There is a CSV document)
Where do I send the ajax request to?
What structures of a Craft plugin do I need?

I'd really appreciate your help.

It's actually quite easy and you don't really need json or a plugin to do it. If you really need it as a plugin, then that's a whole different thing that would need a separate answer.

In your search template file:

<form id="find-contact-form" data-url="/contacts">
    Zip Code
    <input type="text" name="zip">

    <input type="submit" value="Find Contacts"/>
</form>

In your search template javascript file (make sure to include jquery):

$(function() {
    $('#find-contact-form').submit(function(event) {
        event.preventDefault();

        var data = $(this).serialize();
        var url = $(this).attr('data-url');

        $.post(url, data, function(result) {
            $('#contacts').html(result);
        }, 'html')
        .fail(function() {
            //console.log("error");
        });
    });
}

In your contacts.html template:

{% if craft.request.isAjax %}

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

    {% if zip %}
        {% set contacts = craft.entries.section('contacts').zip(zip) %}
        {% if contacts|length %}
            {% for contact in contacts %}

                {{ contact.firstName }} {{ contact.lastName}}

                T {{ contact.telephone}}

            {% endfor %}
        {% else %}
            No contacts found with the zip {{ zip }}.
        {% endif %}
    {% endif %}

{% endif %}

You can also use that same template for your normal contacts page. Just use the clause {% if not craft.request.isAjax %}Put my full page content here.{% endif %}. In fact, the search page can just submit to itself using this technique.


Craft 3: Cache element query or variable assignment Is it possible to cache a variable assignment and/or an element query with TWIG in Craft 3? With Yii2 this is possible, but is there a wrapper to TWIG?

2 use cases:

{% set entries = craft.entries.someThingVerySlowHere() %}
{% set myObject = customVerySlowTwigFunction(...) %}

Why would I want to do that? Let's assume I have 2 blocks in my page, both make use of the variables assigned above, then I can not cache this within the block itself (where the {% cache %} tag belongs, unless I assign/query twice.

The request makes sense, but I thought that Craft did some magic to make sure that a duplicate query/variable-assignment wasn't an issue by re-using the query internally. I have no idea why I think that though.


"Invalid username or password" when registering and logging in a user I'm having a really weird issue with user registration. I've got verification turned off, and logging in after activation turned on, so that when a user registers then checks out, it's a seamless flow. And this works. But the login form at /login does not. Whenever I try to create an account I get this in the logs:

$_POST=array (
  'action' => 'users/saveUser',
  'redirect' => '/confirm-account',
  'firstName' => 'Test',
  'lastName' => 'User',
  'email' => 'testuser9181@gmail.com',
  'password' => REDACTED,
)

$_SESSION=array (
  '8dfc5494412903b44af114111435fc5cYii.CWebUser.flash.error' => 'Invalid username or password.',
  '8dfc5494412903b44af114111435fc5cYii.CWebUser.flashcounters' =>
  array (
    'error' => 0,
  ),
)

Any idea what might be going on here? I have no idea what's causing this, and why it's working on one page and not the other. I can copy/paste the registration code from the checkout page and it will not work at /login. The same template is being extended.


Entries Field Type showing all entries instead of entries selected I am new to craft and twig and need some help showing only added entries to matrix block. What I have now is showing all entries from the section. I may be going about this all wrong, I don't know. I have 11 entries but only want to show the 6 I have added to the block.

    {% for block in entry.sessionsContent.all() %}

{% switch block.type %}

    {% case "sessionsHeader" %}

{{ block.headerTitle }}

    {% case "sessionsIntro" %}

{{ block.introTitle }}

{{ block.introDescription }}

    {% case "sideBlock" %}
    {% if block.isWhiteBackground %}
        {% set divColor = 'white-background' %}
    {% endif %}
    {% if block.isBlockOnTheRight %}
        {% set divPosition = 'float-right' %}
    {% endif %}

{{ block.blockTitle }}

{{ block.blockTeaser }}

{{ block.blockDescription }}

    {% case "backgroundImageDivider" %}

{{ block.dividerTitle }}

{{ block.dividerDescription }}

{{ block.button }}

    {% case "blockTiles" %}

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

{{ entry.sessionTileTitle }}

{{ entry.sessionTileDescription }}

    {% endfor %}

    {% default %}

{% endswitch %}
{% endfor %}

You need to use the relatedTo parameter

{% for entry in craft.entries.relatedTo(block).section('sessionTiles').all() %}

or even more simple the short syntax

{% for sessionTile in block.blockTilesContent.all() %}


Image transform glitches We're having trouble with images being transformed with glitches in them. What would you advise to debug behavior like this?

If you're using GD, try swapping to Imagick.  Also, make sure you're using a recent version of the library as well as the PHP wrapper extension.


Install Failed - Numerous Errors when running with pgsql Getting Numerous errors when trying to test a staging environment with Craft 3.1. States Install Failed - Check Logs which I have and I'm seeing the following logs being given. I don't understand what's causing this problem at all.

When the server starts, it presents me with the following error repeated many times:

data.db (postgresql[daemon]) ::  STATEMENT:  INSERT INTO "resourcepaths" ("path", "hash") VALUES ($1, $2)
data.db (postgresql[daemon]) ::  ERROR:  relation "resourcepaths" does not exist at character 13

Then when I head through the install window it presents me with the following error outputs in the link below (was too much to paste here)

https://paste.ee/p/lrFsi

db.php

<?php

 return [
     'driver'      => 'pgsql',
     'server'      => $_ENV['DATA_DB_HOST'],
     'user'        => $_ENV['DATA_DB_USER'],
     'password'    => $_ENV['DATA_DB_PASS'],
     'database'    => 'gonano',
     'schema'      => 'public',
     'tablePrefix' => '',
     'port'        => 5432
 ];

.env

# The database driver that will be used ('mysql' or 'pgsql')
DB_DRIVER="pgsql"

# The database server name or IP address (usually this is 'localhost' or '127.0.0.1')
DB_SERVER="localhost"

# The database username to connect with
DB_USER="root"

# The database password to connect with
DB_PASSWORD=""

# The name of the database to select
DB_DATABASE=""

# The database schema that will be used (PostgreSQL only)
DB_SCHEMA="public"

# The prefix that should be added to generated table names (only necessary if multiple things are sharing the same database)
DB_TABLE_PREFIX=""

# The port to connect to the database with. Will default to 5432 for PostgreSQL and 3306 for MySQL.
DB_PORT=""

Composer.json

{
  "require": {
    "craftcms/cms": "3.1.15",
    "craftcms/redactor": "2.3.2",
    "lukeyouell/craft-fetch": "1.2.0",
    "nystudio107/craft-seomatic": "3.1.44",
    "verbb/feed-me": "3.1.10",
    "verbb/feed-me-pro": "3.0.4",
    "vlucas/phpdotenv": "^2.4.0"
  },
  "autoload": {
    "psr-4": {
      "modules\\": "modules/"
    }
  },
  "config": {
    "sort-packages": true,
    "optimize-autoloader": true,
    "platform": {
      "php": "7.0"
    }
  },
  "scripts": {
    "post-root-package-install": [
      "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
    ]
  }
}

Project.yaml

https://paste.ee/p/VkgNe#F3NWs50GBWk0M1B7AgmQDuVphbDcwRau

This was due to the following problems on the system, some where 'gotchas' and some were just generic mistakes on my part. Putting this as an answer to help others.

Nanobox's boxfile.yml was classing anything that was in storage/logs/web.log as an [error] but obviously, it's not an error but rather a stack trace. This was fixed by changing it to the following within the boxfile:

    craft[stacktrace]: /app/storage/logs/web.log
    craft[error]: /app/storage/logs/phperrors.log
    php[error]: /data/var/log/php/php_error.log
    php[fpm]: /data/var/log/php-fpm.log

db.php driver was set to mysql when it was using postgres as a database. Changing it to the following 1/2 fixed the problem of installing.

'driver'      => 'pgsql'

.env was correctly set to DB_DRIVER="pgsql" but obviously this didn't match up to what my database was booting up as. This was the final piece of the puzzle.

Essentially the learning from this was make sure your db.php is nicely matched up to your .env file especially regarding your database structure. Make sure you properly set your logs to report as the correct things. As you can see above there are numerous log's craft reports into.


Can GuestEntries edit existing entries? I'm trying to use <input type="hidden" name="entryId" value="{{entry.id}}"> on a GuestEntries form. However, instead of editing the entry with the set ID, it creates a new post.

Am I missing something? Or is this not possible with the GuestEntries plugin.

Correct. It currently only allows for creating new entries, not editing existing ones.


Is there a way to have checkbox field labels translatable? So I have a checkbox field in the new entry editor page. Attached image is an example of said checkbox. Just a standard checkbox field.

Is there a way for these checkboxes to be translatable? I'm redisplaying these checkboxes again in the front-end as filters so users can click the any of the checkboxes and the entries display will be filtered based on their input.

Short of hardcoding all these checkbox values and applying the translate tag on them, I'm not sure what else I can do.

Thanks!

Short of hardcoding all these checkbox values and applying the translate tag on them

That's actually the only way to translate field names, checkbox labels/values and whatnot: taking advantage of Craft's static text translation feature by hard coding the strings you want to translate in a translations file (e.g. /translations/en.php).

An example: If one of your whiskey field's option labels is "Irish", but you want it to be "Welsh" for a certain locale, you can add the following to the returned array in that locale's translation file:

'Irish' => 'Welsh',

Of course, it's also possible to translate the field name itself, i.e.

'Whiskey' => 'Whisky',

There's a big problem though – Craft's static text translation has no idea about context, meaning that it's not possible to tell Craft that the above translations belong to the whiskey field only. In other words, both Whiskey and Irish will be translated across the board. Sometimes that's what you'd want, but often it's not – a translated value may work in one place, but not in another.

One way to solve this, is to use namespacing for all the static strings you want to translate. The naming convention is entirely up to you, but here's how I do it for fields – the following two values are used for the field's name and instructions, respectively:

field.whiskey.name
field.whiskey.instructions

With this namespacing pattern, the first part is the type of content this string belongs to (a field), the second part is the field's handle (which is obviously never translated) and the last part is what the string actually is (the name and the instructions, respectively). This works for other types of content as well, consider section.news.name, entryType.link.name, categoryGroup.editors.name etc.

For "nested" properties, such as a checkbox option's label, I usually write them out like this:

field.whiskey.option.irish.label

For Matrix blocks, the namespacing scheme admittedly is a little bit ridiculous:

field.someMatrixField.block.bio.name
field.someMatrixField.block.bio.text.name
field.someMatrixField.block.bio.text.instructions

The big downside to namespacing field names, option labels, section names etc. is that you have to add a translation for all locales (even your "default" locale), in order to not have the namespaced, "raw" value displayed to your users. In other words, it's definitely a bit more work than just translating plain ol' strings, but the big win is having granular control over all your translated fields, and being able to translate the same value differently for different use cases. It's the only way to go, in my opinion – at least when you have a fair number of strings to translate.

Anyway, here's how your translations file (e.g. /translations/en.php) could look with namespacing for the whiskey field:

return [
    'field.whiskey.name' => 'Whiskey',
    'field.whiskey.option.irish.label' => 'Welsh',
];

As for the frontend, your static string translations will work there, too – just add the |t filter to the labels:

{% for option in entry.whiskey.options %}
    <li>{{ option.label|t }}: {{ option }}</li>
{% endfor %}


Setting a Plugin Object I'm currently using SEO by EtherCreative on Craft 2, one of my pages needs a custom title and description injected into it like this on the docs:

  In some cases, you will not have access to an SEO field, but will want
  to set the page title & description. You can do this by creating a
  custom SEO object using the function below:

craft.seo.custom('The Page Title', 'The page description', $includeDefaultTitleSuffix)

Mine seems to be throwing errors or not doing anything like so:

  {% set seo = craft.seo.custom('Discount codes and vouchers for {{ query }}', 'You searched for {{ query }}. Check out the latest live {{ query }} discount codes & voucher codes for {{ "now"|date("m") }} {{ "now"|date("Y") }} only at Vouchertoday.uk') %}

You can't automatically expand variables inside strings in Twig as you would normally do in PHP.

Instead, you have to concatenate your strings.

{% set seo = craft.seo.custom('Discount codes and vouchers for ' ~ query, 'You searched for ' ~ query ~ '. Check out the latest live ' ~ query ~ ' discount codes & voucher codes for ' ~ now|date('m') ~ ' ' ~ now|date('Y') ~ ' only at Vouchertoday.uk') %}


How to access a freeform field object's properties from an event I am trying to get the value of a field from a freeform event.  Specifically I'm trying to see if a particular checkbox is in a form submission.

craft()->on(
    "freeform_submissions.onBeforeSave",
    function (Event $event) {
        $submission = $event->params["model"];
        $field = $submission['fieldMetadata']['checkbox_handle'];

This works to this point.  I see if I do Craft:dd($field); I have a checkboxField object. But from here on I can't get any info about that field.

        $id = $field->id; // or:
        $handle = $field->handle; // and any other properties

This throws: Fatal error: Cannot access protected property Solspace\Freeform\Library\Composer\Components\Fields\CheckboxField::$id.

If I try:

        $id = $field['id'];

I get: Fatal error: Cannot use object of type Solspace\Freeform\Library\Composer\Components\Fields\CheckboxField as array

The properties and methods are listed at: https://solspace.com/craft/freeform/docs/field/, but I can't access the properties.  I can call the render() method which works and that outputs html.  I'm sure its something obvious, but I'm missing it.

To answer my own question, this is what I found.
The answer is to use get... methods.

craft()->on(
    "freeform_submissions.onBeforeSave",
    function (Event $event) {
        $submission = $event->params["model"];
        $field_item = $submission->fieldMetadata['field_handle'];
        $field_value = $field_item->getValue();

    }
);

The $field_item->getValue() can be $field_item->getId() or $field_item->getHandle() and so on.

The properties listed here: https://solspace.com/craft/freeform/docs/field/ can be used by turning the property into a method and prepending get.


Craft 3 beta - User group total I have tried to find the new way get the total in a user group in php (plugin), but not having much luck... Please help
Assume it starts with Craft::$app->users ?

Use the ActiveRecord from Yii2

$userGroupId = 1 // insert your usergroup Id here
$users = User::find()->groupId($userGroupId)->all();

Or via handle

$userGroup = Craft::$app->userGroups->getGroupByHandle('handle');
$users = User::find()->group($userGroup)->all();

If you mean the number of users in a group with total you just have to do count() instead of all()

To get the users of each group you can do

foreach(Craft::$app->userGroups->getAllGroups() as $userGroup){
    $users = User::find()->group($userGroup)->all();
}


Video embed displays HTML code instead of video We're using Dukt Videos to display a video on this page of our website. However, the video no longer appears on the page and just shows the HTML for the iframe.

Any idea what has happened?

You probably need to add the twig raw filter to your field variable. This will allow twig to interpret the data as safe HTML rather than just plain text.

{{ myFieldVariable|raw }}

Lear more about the raw filter here: http://twig.sensiolabs.org/doc/filters/raw.html


Saving Field Data Custom Craft Plugin I need to create a quick, and small plugin for a client, and am having trouble with the official Craft plugin tutorial.

Here is my base plugin code:

<?php
namespace Craft;

class MailchimpedPlugin extends BasePlugin
{
    function getName()
    {
         return Craft::t('Mailchimped');
    }

    function getVersion()
    {
        return '1.0';
    }

    protected function defineSettings() {
        return array(
            // Very confused about what goes here.
        );
    }

    public function getSettingsHtml() {
        return craft()->templates->render('mailchimped/settings', array(
            'settings' => $this->getSettings()
        ));
    }

}

And here is my settings page code w/ screenshot of what it looks like on the front end:

{% import '_includes/forms' as forms %}

  {{ forms.textField({
    label: "API Key"|t,
    id: 'apiKey',
    name: 'apiKey',
    placeholder: "XXXXXXXXXXXX",
    required: true
  }) }}

  {{ forms.textField({
    label: "List ID"|t,
    id: 'listId',
    name: 'listId',
    placeholder: "d0ffd45cbd",
    required: true
  }) }}

Help

    How To Find Your API Key

    How To Find Your List ID

Basically, all I want to know how to do, is to get the api key and list id field to save and be persisted after the user presses the save button.

I tried reading through the plugin tutorial, and looked at the sample plugin Github page, but honestly, it has to much functionality for a beginner, and is just confusing me even more.

Ideally, the accepted answer will have some code outlining how I would go about this. P.S. I am not looking for an existing plugin, as I want to to do this myself. My company(A studio) uses CraftCMS for their clients websites, so I want to know how to create custom plugins in the future.

It seems all you miss is the define setting and the value attribute in your template, Craft manages the settings for your plugins without any need to edit many things. It stores and loads them automatically. You can handle the entire process on your own and overwrite craft functions but out of the box you have to do nearly nothing.

As a great boilerplate you could create a plugin with Pluginfaktory it has many examples how to manage things like routing, templating and all that kind of stuff.

Just turn the "Settings" lightswitch to on and don't change the "Comments" button.

Anyway here is some example code to store settings
In your Plugin.php you need

 /**
 * Defines the attributes that model your plugin’s available settings.
 *
 * @return array
 */
protected function defineSettings()
{
    // this is an array with all the settings the user may change.
    // Open the `AttributeType` file to see a full list. Eg. Integer,
    // String, JSON, Enum.... there are many ready to use data types, and of
    // course you could define validation rules like min length, max length,
    // in range and such
    return array(
        'apiKey' => array(AttributeType::String, 'label' => 'Your Api Key', 'default' => 'XXXX'),
        'listId' => array(AttributeType::String),
    );
}

/**
 * Returns the HTML that displays your plugin’s settings.
 *
 * @return mixed
 */
public function getSettingsHtml()
{
   return craft()->templates->render('mailchimped/settings', array(
       'settings' => $this->getSettings()
   ));
}

And your template

{% import "_includes/forms" as forms %}

{{ forms.textField({
    label: 'Some Setting',
    instructions: 'Enter some setting here.',
    id: 'apiKey',
    name: 'apiKey',
    value: settings['apiKey']})
}}

{{ forms.textField({
    label: 'Some Setting',
    instructions: 'Enter some setting here.',
    id: 'listId',
    name: 'listId',
    value: settings['listId']})
}}

Yeah, thats finally it... you can access those with from everywhere

MailchimpedPlugin::getSettings()['listId']

Or

$settings = MailchimpedPlugin::getSettings();
$data = $settings->getAttributes();


Does Craft Commerce support One Time Password and Social Login features? I have just started reviewing this plugin for e-commerce development. Fully featured though it is, I wanted to know if Craft Commerce can also support custom auth (login and registration) features such as One Time Password using a mobile cell number and Social Login through facebook and twitter?

Is it possible to build or use an existing plugin around these features?

Craft Pro gives you the ability to add multiple user accounts to your site. Craft Commerce is a plugin that extends Craft so user accounts and everything that goes with them are available to use.

There is a plugin to enable social logins (currently in beta) made by Dukt that you may find helpful.


How can I restrict assets on a per-file basis? I found this post about restricting an entire asset source and placing it below the root level: Is it possible to have secure (private) assets?

What I'd really like to do is be able to set the members-only restriction on a per-file basis, perhaps with a lightswitch field.

The imagined flow would be:

user clicks a file link (anywhere, or even has a direct URL to the file)
.htaccess sends all .pdf, .doc, etc requests to a download checker page
download checker page sees if the requested file has the lightswitch checked
if no, download the file
if yes,

if logged in, download the file
if not logged in, show the registration / login page

upon login or registration, start the file download

I'm still relatively new to Craft and have the feeling there may be specific twig/craft abilities that make this — or something very similar — simple. I don't necessarily need the code handed to me, just some ideas about what tools are available to help with this process.

Why don't you just set up two separate asset sources, one default one with files being freely accessible and one source with access for logged-in users only by making use of that Internal Assets Plugin you mentioned.

Instead of managing the rights with a lightswitch you would upload or move the assets in the right source.

Another option would be to have two asset fields for your entry type, one configured for each source. And you could then always hide one of them with a lightswitch using the brand new Reasons plugin.


Count table field values in certain section I would like to know, how many values are saved in the table field called "artikelnummer" with the field name "artikel". The section is called "bikes". I tried:

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

{% for entry in entries %}
  {% for row in entry.artikelnummer %}
    {{ row.artikel|length }}
  {% endfor %}
{% endfor %}

Thanks!

You can get the total amount of rows like this:

{% set totalcount = 0 %}
{% for entry in entries %}
    {% set totalcount = totalcount + entry.artikelnummer|length %}
{% endfor %}

Edit

In the loop you add the length to the totalCount.


Does Craft have a discussion forum and ratings add-on? I am thinking about switching to Craft from EE but need various add-ons such as a discussion forum and ratings function (with the ability to have sub-ratings), and advanced search. I did not see anything like that in the plugins page but wanted to be sure before making this decision.

Thanks,
Geoff

There is no discussion forum available in craft as of now but people that need that function seem to be using Vanila Forums and just integrating with single sign-on which seems to work just fine.

There is this which could work for ratings: http://plugins.supercooldesign.co.uk/plugin/button-box which is a bit simple but depends on what you need.

There is also this which could allow 'likes' https://dukt.net/craft/like

I thought I had seen something with a bit more advanced ratings but can't seem to find it now. At the end of the day though Craft > ExpressionEngine in pretty much every way. There are very few things EE can do better than Craft and even then it's usually due to a third party add-on being available there that is not yet available in Craft due to it's maturity.


paymentMethodID payment method id cannot be blank We're using Craft Commerce 3.2.11 and Stripe as the payment gateway.  We can put through a purchase using test cards no problem, but when we try with an actual card we get the message:
paymentMethodID payment method id cannot be blank
Is there anything else we need to do to put through a live card?

Update: it looks like it was an issue with the secure cert on the site.  Once we got that updated, purchases are going through as normal.


Using SSL for entire website on Arcustech server I want to use SSL (https) for my entire website which is hosted on Arcustech.  I came across two instructions, one on Craft's site which discusses forcing SSL on the CP and the other is from Arcustech's site which discusses forcing SSL on entire site.  I'm not sure if I can just use the Arcustech's version or if I need a combo because I want the CP to be SSL too.

Here's the code for the two versions:

Craft Forcing SSL on CP (direct link)

<IfModule mod_rewrite.c>
RewriteEngine On

# Force SSL for CP requests
RewriteCond %{HTTP_HOST} example\.com [NC]
RewriteCond %{REQUEST_URI} ^/admin/ [NC]
RewriteCond %{HTTPS} !=on
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [NC,R=301,L]

Arcustech Forcing SSL for entire site

RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !^https
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

Thank you!

Lori

This worked for me on the Arcustech server:

Put this code in the root .htaccess file:

<IfModule mod_rewrite.c>
RewriteEngine On

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

# SSL only
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !^https
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

As RitterKnight mentioned you also need to modify your site's "Site URL" in Settings>General to be https://.


How to process POST and entry fields when using same form for Add as Edit on front end? I use the same form for adding an entry on the front end as I do for editing it.

So when editing it, we need to insert the field values in the fields.

When editing or adding it we also need to re-populate the values in the form from the POST submission in case of form validation error.

So this means checking if there is a post request, assigning the values from the post to some variables used in the form, but if not then assigning them from the entry.

I always think the method I use is a bit of a hack, and there should be some built in way to do it, but cant find it.

Below is the most efficient code I have yet but it's needed for each field. What it does is if there is a post entry then to assign it to the entry object, so that way in my form the value is just the entry.myCustomField which is set whether we're editing or posting (priority to post value if it exists).

But I wanted to know if there is an even more efficient way, something built in, or if I could even iterate through all post fields automatically without having to create the below code for each field.

{% if craft.request.getPost('fields.myCustomField') is not null %}
    {% set entry = entry|merge({'myCustomField': craft.request.getPost('fields.myCustomField')}) %}
{% endif %}

I did think maybe I could just assign the whole POST to the entry as follows which would be ideal, but I get the error 'The merge filter only works with arrays or "Traversable"'

{% if craft.request.getPost('fields') is not null %}
    {% set entry = entry|merge(craft.request.getPost('fields')) %}
{% endif %}

Another idea I had was to get all the fields from the section and iterate through them, but I don't know how I can create variables named after the values of the field handles.

{% set fields = craft.sections.getSectionByHandle('mySection').getEntryTypes()[0].getFieldLayout().getFields() %}
{% for field in fields %}
    {# dont know how to create each field named after the field.handle so I can enter my code above once and iterate over it per field #}
{% endfor %}

This may not be possible but can you not just make your form itself an include and have a "create" template and another "edit" template which have their own logic but include the same base form?


How to use twig parent function on nested blocks I'm not sure if it is appropriate to post twig questions on this forum? I have a question about nested blocks and using the twig "parent" function. I'm running into unexpected behaviour on a craft site i'm building.

My parent and child template layouts.

{# Parent Template #}
{% block breadcrumbs %}
    {% block crumb %}

    {% endblock %}
{% endblock %}

{# Child Template #}
{% block breadcrumbs %}
    {{ parent() }}
    {% block crumb %}
        My custom content
    {% endblock %}
{% endblock %}

What I'm trying to achieve

On my child template, I'm trying to retain the content in block breadcrumbs but override the content in block crumb.
However when I use the parent function in my child template, it does not respect "my custom content" and uses the block crumb content defined in the parent template.

Try to keep the blocks separate in your child template. That's how it's done in a comparable example in the Twig Documentation.

Parent Template:

{% block breadcrumbs %}
    {% block crumb %}
    {% endblock %}
{% endblock %}

Child Template:

{% extends "parent.html" %}

{% block breadcrumbs %}
    {{ parent() }}
{% endblock %}

{% block crumb %}
    My custom content
{% endblock %}

.

Edit:

If you're not adding any content to your "breadcrumbs" block from the child template, you can also omit that block completely:

{% extends "parent.html" %}

{% block crumb %}
    My custom content
{% endblock %}


Stripe order hangs when submitted Folks:
A site I have works great in test and has been pushed live. Orders do not complete on the live site. When the transaction is submitted "Card confirmed" appears (I'm riffing off the included templates) and the page hangs. No transaction goes to Stripe and no confirmation email is fired.
I have added the live keys so that's not the issue. Perhaps webhooks are needed?
Any help would be great.

OK, this was caused by a simple oversight on my part. To simplify matters for anyone else trying to set up Stripe, here is your checklist:
In your templates

Verify that you are using the latest version of JQuery.
Verify that you are NOT using deprecated onLoad. It should be  $('#paymentMethodId').on('load', function(){, not $('#paymentMethodId').onLoad(function(){

At Stripe:

Set up a webhook endpoint. Get your endpoint URL from the Stripe gateway page in Commerce.
Set the webhook to accept "All Events". If you read the docs you can narrow this down considerably.
Copy the webhook signing secret. You will need this for Commerce.

In the Commerce Stripe gateway page:

Enter your publishable and secret API keys.
Enter the webhook signing secret in the Webhook Signing Secret field for the Stripe gateway. Preferably via the .env file like a good Craft citizen.

In your config > general.php file:

Disable CSRF for your webhook URL as detailed here: https://craftcms.stackexchange.com/a/21304/4506

I hope I didn't miss anything.


How to check for an HTML element in a rich text field? I want to do something special in my template if there's an HTML table in the rich text field. I tried this:

{% if "</table>" in entry.richTextFieldHandle %}

but it doesn't work. How can I do this? Or can you think of a better way?

Thanks.

You can get this to work if you first escape your string using Twig escape filter. Not exactly sure what's going on, but it'll only work for me if I make Twig double escape the string like so:

{% set strategy = 'html' %}
{% set doubleEscapedString = entry.richTextFieldHandle|escape(strategy) %}
{% set hasTable = '&lt;/table&gt;' in doubleEscapedString %}

<div class="{{ hasTable ? 'hasTable' : 'hasNoTable' }}">
    {{ entry.richTextFieldHandle }}
</div>


FeedMe SSL error - cURL error 35: SSL connect error I'm getting an error when trying to access an endpoint over ssl in FeedMe. eg https://jsonplaceholder.typicode.com/posts

The error is
cURL error 35: SSL connect error

Error reported in web.log is
[verbb\feedme\base\PluginTrait::error] Test: Unable to reach https://jsonplaceholder.typicode.com/posts. Message: cURL error 35: SSL connect error (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)

I've tried running curl directly from commandline on the server and it runs fine:
curl https://jsonplaceholder.typicode.com/posts prints the JSON.

PHP: 7.2.5
cURL: 7.19.7

Most likely the PHP curl version that's on your box is trying to connect to the endpoint using an older SSL protocol (TLS 1.0, 1.1, etc.) and the endpoint requires something higher (TLS 1.2, 1.3, etc.).

http://blog.techstacks.com/2010/03/3-common-causes-of-unknown-ssl-protocol-errors-with-curl.html

The command line version of curl is probably using a newer protocol.


Sprout Forms - Custom Form Notification Recipients With sproutForms.onBeforeSaveEntry I've got an existing service based site that uses Sprout Forms to request quotes. The quote form lives on all services pages in a sidebar (and the submissions have an entries field keeping track of which service the submission came from).

I've just added some fields into the services entry to allow them to override where the quote form goes.

Now I need to make this work. I have a plugin listening for sproutForms.onBeforeSaveEntry events, and when it receives them I'm wanting it to adjust where it sends the notification to.

Is this possible? Is it possible to modify notificationRecipients on an individual event or is this against the form (and in either case how do I do this if I have a SproutForms_OnBeforeSaveEntryEvent)?

In either case (as I can live with the former) a code example would be amazing.

Based on the event you are referencing, I believe this is a question about Sprout Forms for Craft 2. In Sprout Forms for Craft 3, notifications are handled a differently.

In Sprout Forms for Craft 2, the event you'll want to use for this is the SproutForms_OnBeforePopulateEntryEvent.

You're not able to modify which value gets set directly, so you'll have to swap in the value you want using Craft Object syntax.

In your notificationRecipients field, add a value using Craft Object Syntax: {myRecipientsEmail}. Once you have called sproutForms.onBeforePopulateEntryEvent you can modify the $_POST data that gets processed when assigning the recipient value and it sure it has the value you want: $_POST['myRecipientsEmail'] = 'so-and-so@website.com'


Dropdown empty option in order for my client to have the choice of selecting options or not, I entered an empty (blank) option in a dropdown field.

In the frontend, I use this code:

{% if entry.dropdownFieldHandle|length %}

Title

{{ entry.dropdownFieldHandle }}

{% endif %}

The problem is even if the client chooses the blank option, it still makes the code appear.

Where am I wrong?

If the client selects an empty value you probably will get an empty value back.

Try this:

{# Make sure we have a value #}
{% if entry.dropdownFieldHandle != "" %}

Title

{{ entry.dropdownFieldHandle }}

{% endif %}


Change the fill or stroke colour of an SVG using a field value? Is it possible to change the fill or stroke colour of an SVG using a value pulled from a custom field?  For example:
{{ svg('@webroot/_dist/stat/link-arrow.svg')|attr({
    stroke: '{{ entry.myCustomFieldValue }}'
}) }}

I can only get it to partially work by using a class but unfortunately there are a number of SVGs on the page so we'd also need to change all the class names :/ - and it's ugly!
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     viewBox="0 0 37.9 20.1" style="enable-background:new 0 0 37.9 20.1;" xml:space="preserve">
<style type="text/css">
    .st0{fill:none;stroke:{{entry.myCustomFieldValue }};stroke-width:2;}
</style>
<g transform="translate(0 0.526)">
    <line class="st0" x1="0" y1="9.8" x2="36.5" y2="9.8"/>
    <g transform="translate(31.688 1)">
        <path class="st0" d="M-1-1l2.8,4.5l3.6,5.8"/>
        <path class="st0" d="M-1,18l2.4-3.8l0,0l4-6.4"/>
    </g>
</g>
</svg>

Because you are wrapping {{ entry.myCustomFieldValue }} in ', you are passing it as a string instead of its value, that's why you then see it as is in your result. Try:
{{ svg('@webroot/_dist/stat/link-arrow.svg')|attr({
    stroke: entry.myCustomFieldValue
}) }}


How can I create global code variables? I'm wondering if there's any equivalent to the Yii "params" array I can set on Twig code template level for re-use throughout all my templates using Twig syntax?

Besides saving the variable in a field (e.g. global set) you could also add a "Environment Variable" to
your general.php file:

'myGlobalVariable' => 'I am available in all environments'

but you can only access it from Twig, it's not possible to update it:

{{ craft.config.myGlobalVariable }}

If you do need to update from  your Twig templates, you should make a custom plugin / add to your Business Logic plugin.
There's various options to make a variable available in your Twig templates:

add a "Template Variable" to the {{ craft }} global variable

or with a Twig Extention:

add a new Global Variable using getGlobals()
add a Twig function with new Twig_SimpleFunction()

With a plugin you have these options to save your value (and update with a custom Twig function):

in a Record, update with $record->save()
directly in the plugin settings, update with craft()->plugins->savePluginSettings() (→ read more on SE)
with a config.php file in the plugin folder, not possible to update with Twig (→ read more on SE)
hard code it into the plugin PHP ;)


How can I iterate through my entries? I want to iterate through my entries on the click of a 'next' and 'previous' button.

I have started off using getNext() and getPrev() by I'm in a bit of a rut.

{% set entry = craft.entries.section('comics').first() %}
{% set asset = entry.comic.first() %}
{% set params = craft.entries.section('comics').order('id asc') %}
{% set prevEntry = entry.getPrev(params) %}
{% set prevAsset = prevEntry.comic.first() %}
{% set nextEntry = entry.getNext(params) %}
{% set nextAsset = nextEntry.comic.first() %}

This is the Twig code. To display the prevEntry I have been using jQuery. Here is that code.

    function prevComic() {
      var $prevTitle = "{{ prevEntry.title }}";
      $(".comic-title").text($prevTitle);
      $(".comic").attr('src', '{{ prevAsset.url }}');
      $(".comic-caption").text("{{ prevEntry.body }}");
    };
    function nextComic() {
      var $nextTitle = "{{ nextEntry.title }}";
      $(".comic-title").text($nextTitle);
      $(".comic").attr('src', '{{ nextAsset.url }}');
      $(".comic-caption").text("{{ nextEntry.body }}");
    };

Then I'm using onclick() on the buttons to call the functions.
All I really want is for the 'previous' button to give me the previous entry to the entry currently displayed, and for the 'next' button to give me the next entry to the entry currently displayed.
Can anyone help me?
Thank you :)

The way you want to achieve this won't work. Twig is just a render engine for php so you can't execute it during your runtime. You could load all entries during the page load and create a twig filter to json_decode them in order to gain access with javascript or you can do something really really nasty like

{% set allEntries = craft.entries.section('comics').order('id asc') %}
<script>
    var entries = [];
    {% for entry in allEntries %}
        entries.push({
            title: "{{ entry.title }}",
            body: "{{ entry.body }}",
            url: "{{ entry.getUrl() }}"
            // .....
        });
    {% endfor %}
</script>

To get an array of objects in javascript. But I would not suggest this. The clean way would be to create an ajax request and fetch the entry with php

Have a look at this to learn how to create an ajax request to a controller. You would have to change your controller to:

public function actionSearchEntry()
{
    $id = craft()->request->getParam('id');
    $element = craft()->elements->getElementById($id);

    $criteria = craft()->elements->getCriteria(ElementType::Entry);
    $criteria->section = "comics";
    $criteria->orderBy = "id asc";
    if(!$nextElement = $element->getNext($criteria)){
        $this->returnJson([
            'success'   => false
        ]);
    }

    $this->returnJson([
        'element'      => [
            'title' => $nextElement->title,
            'body'  => $nextElement->body,
            // ....
            'id'    => $nextElement->id
        ],
        'success'   => true
    ]);
}

In your javascript you'll create an ajax request and change the values to the one you received if it was successful (if not there will be probably no other entries.


Guest Entries ignores redirect field? I'm looking into a project another developer has done, and after submission of a front-end form the system is ignoring the redirect set in the template. The form is being submitted and saved correctly though.

Anyone got any ideas why this would be?

<form method="post" action="" accept-charset="UTF-8" id="download-subscribe">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="guestEntries/saveEntry">
    <input type="hidden" name="redirect" value="/downloads/available-downloads/">
    <input type="hidden" name="sectionId" value="11">

        First Name
        <input id="firstName" type="text" name="fields[firstName]">

    ...

</form>

Possible complications, which i expect aren't a problem but might be worth knowing:

The form is in an include rather than in the template directly
The form is being spat out mid-way through a matrix loop (i.e., if the loop is count 2 then first spit out the form).

Answer: As Brad guessed; the problem was a plugin, specifically Sprout Invisible Captcha. Disabling that allowed the form redirect to work properly again.


customised slugs using custom field I have a 'Profile' channel that gives the profile of people.

I have 'Last name' as the title, 'first name' and I'd like to use first name in the slug rather than have to add the first name to the title and then need to create another field to store the last name.

I thought, similar to {entry.type} I could've gone for {entry.firstName} but that doesn't work.

Possible?

Firstly I'd recommend splitting the first name and last name into seperate fields. That way in your templates it would look nicer:

{{ member.firstNameField }} {{ member.lastNameField }}

than having:

{{ member.firstNameField }} {{ member.title }}

when outputting their names.

Once you have done that, in your entry type settings you can set the entry title to run off these first name and last name fields:

{firstNameField} {lastNameField}

The slug will be automatically generated from this as well. I may have mis-understood your question, but I hope that helps.


PHP Core Warning – yii\base\ErrorException Module 'newrelic' already loaded craft 3 I upgraded Craft 2 to Craft 3.3. Sometimes I am getting an error in admin like below when saving entries or taking some URL.

  PHP Core Warning – yii\base\ErrorException Module 'newrelic' already loaded craft 3

Please help.

Not really related to Craft or the update from Craft 2 to 3.  You'll probably want to contact your hosting provider.  It sounds like there are multiple attempts at loading the newrelic module in your php.ini file.


How I can sort my entry that belong to 3 section on date? {% set blog = craft.entries.section('blog').all() %}
{% set news = craft.entries.section('news').all() %}
{% set caseStudies = craft.entries.section('caseStudies').all() %}
{% set allEntries = blog|merge(news)|merge(caseStudies) %}
{% for entry in allEntries %}
 <span>
       {{entry.nameSection}} | {{entry.dateNews|date("F  d, Y")}}
</span>
<h3 class="title post-title">
      {{entry.title}}
</h3>
{% endfor %}

Try chaining the sections together like:

{% set allEntries = craft.entries({
  section: ['blog', 'news', 'caseStudies']
}).orderBy('elements.dateCreated asc').all() %}

Then

{% for entry in allEntries %}
   <span>
       {{entry.nameSection}} | {{entry.dateNews|date("F  d, Y")}}
   </span>

   <h3 class="title post-title">
       {{entry.title}}
   </h3>
{% endfor %}


Unable to load the "Craft\xyz" runtime after Craft update After updating from Craft CMS 2.6.2973 to Craft CMS 2.6.2981 I get the following error message:
"Unable to load the "Craft\xyz" runtime after Craft update"

"Craft\xyz" is a Twig extension
Fails in [install folder]\craft\app\vendor\twig\twig\lib\Twig\Environment.php line 900 (Twig_Environment::getRuntime())
Twig_Environment::runtimes is an empty array

Anyone else experienced this problem, and know what is causing it?

Thanks in advance!

Fixed by changing:

class xyz extends \Twig_Extension
{
    //...
    public function getFunctions()
    {
        return array(
            new \Twig_SimpleFunction('kex_cache_breaker', array(__CLASS__, 'cacheBreaker'))
        );
    }
    //...
}

To:

class xyz extends \Twig_Extension
{
    //...
    public function getFunctions()
    {
        return array(
            new \Twig_SimpleFunction('kex_cache_breaker', array($this, 'cacheBreaker'))
        );
    }
    //...
}


Accessing SEOmatic meta via controller action in Element API triggers HTTPForbiddenException I'm attempting to fetch SEO meta for entries inside of an element API, roughly following the advice in Element API integration
Below is the exact code in my element-api.php:
<?php

use craft\elements\Entry;

return [
    'endpoints' => [
        'api.json' => function() {
            return [
                'elementType' => Entry::class,
                'criteria' => [],
                'transformer' => function(Entry $entry) {
                    $seo = Craft::$app->runAction('seomatic/meta-container/all-meta-containers', [
                        'uri' => $entry->uri,
                        'siteId' => null,
                        'asArray' => true,
                    ])->data;

                    return $seo;
                },
            ];
        },
    ]
];

If I hit this endpoint directly in a browser - e.g. http://my-url.test/api.json - it returns a response exactly as expected. However, if I try to hit the endpoint using an external GET requestion with Accept: application/json (I'm using https://paw.cloud, specifically), I get back an error exception of yii\\web\\ForbiddenHttpException
Is there something about runAction inside of an Element API call that isn't allowed? Is there something I need to do to allow this in outside requests?

Probably you need to turn on the Meta Container Endpoint Access option in SEOmatic -> Plugin Settings -> Endpoints
This is intentionally disabled by default, you need to enable it if you intend to use it.


Set OrderBy on Grouped Query Involving Smart Map Field I'm working with a Structure of resort locations. Each resort has a field address which is a Smart Map field. I'm trying to create an initial display page that groups the resorts based on their state (a Smart Map address part), but I would like to order the output first based on the state and then by resort title.
Something like.

Arkansas
Awesome Place
Best Place
Alabama
Alright Place
Better Place
Florida

I'm partially there using the following:
{% set resorts = craft.entries().section('resortsList').orderBy('title ASC').all() %}
{% set resortsByState = resorts|group('address.state') %}

And then outputting the list...
{% for state, resortsInState in resortsByState %}

{{ state }}

  {% for resort in resortsInState %}

{{ resort.link }} - {{ resort.address.state }}

  {% endfor %}
{% endfor %}

This gives me the list grouped by the state and ordered by the resort title which gets me partially there. I've tried adding address.state as part of the ordering declaration, but I'm only getting errors (Unknown column 'address.state' in 'order clause'). Is there a proper way I should be doing this?

Okay, I've been able to solve this and figured I'd share what I discovered. The key for each group is the value of the state so really what I was after here was a key sort and just didn't realize it. So I found Michael Rog's "SuperSort" plugin which has a twig filter for running a ksort and that addressed it perfectly for me making a small adjustment to use supersort in the response.

{% set resorts = craft.entries().section('resortsList').orderBy('title ASC').all() %}
{% set resortsByState = resorts|group('address.state')|supersort('ksort') %}

I'm interested in other solutions too that don't require a plugin, but this particular direction got things going for me.


Saving asset programatically, eg via API I'm working on a plugin in Craft 3 that is fetching a file reference (URL) via an API.

I want to fetch the file and save it locally as an Asset. I've tried to do this via Craft::$app->getElements()->saveElement() but am getting the following error:

New Location cannot be blank.

Any thoughts on this issue or where to dig a bit deeper to resolve?

Cole

Not an answer directly to your question but a general function to upload an asset in PHP. In my case $file is an uploaded file in the $_FILES array. You can download a file per url and insert it's tmp_name and name manually

/**
 * Upload a file
 *
 * @param $file
 * @return int|null|string
 * @throws \Throwable
 * @throws \craft\errors\ElementNotFoundException
 * @throws \yii\base\Exception
 */
public function uploadImage($file)
{
    $assets = Craft::$app->getAssets();
    $folderId = 1; //<- insert your folder id

    /** @var \craft\models\VolumeFolder $folder */
    $folder = $assets->findFolder(['id' => $folderId]);

    $asset = new Asset();
    $asset->tempFilePath = $file['tmp_name'];
    $asset->filename = $file['name'];
    $asset->newFolderId = $folder->id;
    $asset->volumeId = $folder->volumeId;
    $asset->avoidFilenameConflicts = true;
    $asset->setScenario(Asset::SCENARIO_CREATE);

    $result = Craft::$app->getElements()->saveElement($asset);

    // In case of error, let user know about it.
    if ($result === false) {
        throw new Exception('Error while upload asset');
    }

    return $asset->id;
}


Images missing from Entries, but still on server Have a bit of an issue.

Recently, a site I work had its asset index rebuilt upon finishing for some reason all images associated to entries are now no longer attached. They are still on the server and in the database.

How would one go about linking these back-up as I don't fancy going through every entry to reassociate the image manually.

Thank you for your help.

Clear the caches after updating the assets index, asset indexing data at the very least, though I'd normally clear everything to be sure.


public vs public_html for git workflow deployment in apache? I have a website setup in Craft multi-environment config for git workflow with a development branch automatically deploying via deploybot from a bitbucket repository.   I want to add an additional live server for manual deployment via deploybot, but I'm concerned about the folder structure.  I know the public folder in Craft is just a stand in for web_root, but if I allow git to deploy to the server root, won't it try to make a new public folder by default?

Staging setup
/home/user/public_html/staging/public/index.php

Live site
/home/user/public_html/index.php instead of
/home/user/public/index.php

I have seen where I can add a symlink to point one folder to another, but I don't think I can point public_html to a new public folder as I have other subdomains stored in public_html.   Should I just rename public in my Craft files to public_html in the local and staging files, or can I symlink public to public_html without abandoning my existing files?

Generally, you can make the Craft public folder whatever you want it to be. That allows you to deploy to any folder you like.

For example, I deploy to a public_html on one server, public on another and web on another server. Each of those directories are the web root of their respective site.

The only thing(s) within the public (or whatever you call it) directory is/are the index.php file (and whatever other js/css etc type files) you may have. As long as you can tell that file where the craft directory is (usually one level above the web root) - you should be golden!


How to query an entry by a custom field in Craft 3 How do you query an Element by a custom field in Craft 3?
My first try, according to craftcms/docs was:

$country = Entry::find()
                ->section('countries')
                ->where(['LIKE', 'code', 'CA'])->one()

But this throws an exception. Here code is a custom text field. I've also tried some answers on stack exchange and many other combinations but they're for Craft 2 and neither they work.

Your where clause is actually a query based where so you have to select the database fields instead of the field handles. When you want to do it with where you have to make it like that

$country  = Entry::find()->section('countries')->where([
    'content.field_code'    => ['like', 'CA']
])->all();

This is the correct documentation right now.

Edit: you might want to call the getRawSql() function in order to see the query and all selected rows. When you use your code you'll see why your sql throws an exception

Edit2:
You don't need to read the following part, these are just some explanations to the content.field_codepart - if you are interested in Craft go ahead if not skip it.

Not sure if you know that but Craft adds the prefix field_ to every fieldhandle in the content table (the table where Craft stores your entire content). So for every field you create the database includes a column field_+$field->handle that's why you have to include the field_ in before your handle in the query above.

However if you are going to change that prefix for any reasons you could use Craft::$app->getContent()->fieldColumnPrefix in order to fetch the current column prefix. I doubt many people will do this but I wanted to make sure you know it.

And the ElementQuery (the class you actually call when you do Entry::find() contains the following code

/**
 * @var string|null The content table that will be joined by this query.
 */
public $contentTable = '{{%content}}';

This is hard coded so only the developers from craft can make really deep changes here (unless you overwrite the structure in Craft)

So in the end: craft left joins the content table and selects all columns. That's why you have to use content.field_+$fieldHandle


Is there a way to see the total number of entries in a channel in the CP? Is there a plugin or something I'm missing in the CP to just see how many entries are under any given channel or structure?

You're looking for the Content Stats plugin by Will Browar:

  https://github.com/wbrowar/contentstats


Can you set async defer when using {% includeJsFile %}? Is there a way to set async defer on a <script> tag with the built in:

{% includeJsFile %}

It's for Google Maps e.g.:

<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"
async defer></script>

I'd still like to be able to output this at the bottom of the layout from within another template. Is this possible?

As of Craft 3 (Tested using RC5) you can do it like this:

{% do view.registerJsFile("path/to/script.js", {"async":"async", "defer":"defer"}) %}

Source: Documentation for Yii's view.registerJsFile()


Asset integration with Microsoft Azure Storage in Craft 3 I'm developing a site using the Craft 3 and I can't figure out how to connect assets with Microsoft Azure Storage.

I found plugin for Amazon S3 but not available similar plugin for azure.

Any help will be appreciated.

You could try fronting Blob with s3proxy as a workaround.