Structure dynamic 301 redirects Is there a way to automatically create a 301 redirect on a structure entry if it gets reordered into a new group. For example the original entry lives under /section-1/entry-title and it gets moved to /section-2/entry-title. So if the original url is indexed it gets redirected to the new location without the client needing to do anything.

Thanks for the help

Nothing clever I can think of, but it's an interesting idea.

You can either manually setup the redirects in your .htaccess file, or there are a couple of plugins that appear to let you manually manage redirects from the control panel.

A feature request to the plugin developers might be to get them to add support to listening to an (as-of-yet non-existent) "onMoveStructuredEntry" event in Craft that automatically creates the redirect for you.


Problem after renaming section I had a section called vision which i renamed to articles. I did so by going in to sections and clicking the section and then changing..

Handle, Entry URL Format and Entry Template. I also copied and renamed all the template files.

Now i can load up the main page as server/articles. But none of the entry pages will load and I get a 404 error.

When i look at the entries they are still there and now say the uri is: articles/article-name and the data is all there..

Did i miss something that needs to happen to rename a section?

Thanks. I think this is what happened. When i saved the entry change i did change the Enrty Template name. However, it seemed to have generated it back to articles/_entry.

Then i went in again and updated the name back to the real name i was using.


Remove a Control Panel Section I've made a new plugin for Craft 3 using https://pluginfactory.io/, including everything possible just in case I needed it. Now that my project is coming to a close I'm going back through to take out what I didn't end up needing (I now realize this was not the wisest way). I can't seem to take out the Settings and Control Panel sections, even though my composer.json has:

...
"extra": {
  "hasCpSettings": false,
  "hasCpSection": false,
}
...

I'm not redeclaring those as true anywhere else...is there something else I should do to remove those parts?

Craft itself is caching this data. Once you've removed those lines from your composer.json file, you'll also need to remove them from the cached plugins.php file in Craft.

Open this file...

  /vendor/craftcms/plugins.php

Then find your plugin. Remove the relevant lines from there, and save the file.

For this reason I actually recommend declaring hasCpSettings and hasCpSection the "old fashioned way"... within your plugin's main PHP file.

Yes, it's possible to declare those values via PHP as well. And if you declare them via PHP, they won't get cached in Craft's plugins.php file.

  https://docs.craftcms.com/api/v3/craft-base-plugintrait.html#property-hascpsection
  https://docs.craftcms.com/api/v3/craft-base-plugintrait.html#property-hascpsettings


Upload Assets Manually Is it possible to upload assets into the folders listed in the asset section on the server manually/directly? And then "sync up" the system so the ui sees these?

Used to be able to do this in expression engine via a sync button and i don't see how to do that here, but perhaps im missing the trick?

Thanks

Yes, after uploading via FTP, you will need to tell Craft to go and index the new assets: Settings > Tools > Update Asset Indexes


Blank screen for /admin and public site with Craft 3 I've just installed Craft 3 RC with Composer. Everything went fine. I moved the contents of the web directory to the public_html folder.

domain.com/admin
and
domain.com

both give blank screens. Where should I start my troubleshooting?

Folder structure

.composer
craft
  config
  modules
  storage
  etc...
public_html
  /cpresources
  .htaccess
  index.php
  web.config
  test.php

If I add an index.html to the public_html folder, I can access it via domain.com, but I cannot access domain.com/test.php from public_html.

Thanks,
Ben

What you'll want to do is change the CRAFT_BASE_PATH in your index.php file.

Look for line 7, and change this:

define('CRAFT_BASE_PATH', dirname("__DIR__"));

to this:

define('CRAFT_BASE_PATH', dirname('./'));

I had this issue as well, being used to doing the same thing with Craft 2, changing the $craftPath variable.


Updating craft user fields from plugin I have 2 forms on my site, one that registers for the WHOLE site and one that registers for just the downloads on the site. I wrote this custom function to change the user group if the email existed. So basically what i'm going for here is if someone signed up for ONLY the downloads and wanted to signup for the whole site to let them use their email they used to sign up originally.

So basically they fill out the sign up form use the same email etc.

Currently the code i have isn't working properly. It changes the user group and allows the user to sign up IF they already signed up, however it won't update the rest of my user fields on the form. If a new user comes to the site and tries to sign up for the whole site the signup form doesn't work, it doesn't save the user, just redirects to the login page.

To Create a user do

$request = Craft::$app->getRequest();
$user = new User();
$user->username         = $request->getBodyParam('username');
$user->email            = $request->getBodyParam('email');
$user->newPassword      = $request->getBodyParam('password');
$user->firstName        = $request->getBodyParam('firstName');
$user->lastName         = $request->getBodyParam('firstName');
$user->setScenario(User::SCENARIO_REGISTRATION);
Craft::$app->getElements()->saveElement($user);

To update a user

$request            = Craft::$app->getRequest();
$user->username     = $request->getBodyParam('username');
$user->email        = $request->getBodyParam('email');
$user->newPassword  = $request->getBodyParam('password');
$user->firstName    = $request->getBodyParam('firstName');
$user->lastName     = $request->getBodyParam('firstName');
$user->setScenario(User::SCENARIO_LIVE);
Craft::$app->getElements()->saveElement($user);

So it's basically the same except the scenario


Programatically creating a user not appearing in Users index table I'm trying to programatically create a user (once the user submits a form through Sprout Forms). The user doesn't seem to appear in the Users section of the CP.

I've ensured the user is being added correctly - I can even see a row in the craft_users database table. Going directly to admin/users/349 (the ID of the newly added user) shows all the user details.

It's been suggested that I need to index the new element data - but not sure how to do this.

$content = $entry->getContent();

$user = new UserModel();
$user->username         = $content['email'];
$user->email            = $content['email'];
$user->unverifiedEmail  = $content['email'];
$user->firstName        = $content['firstName'];
$user->lastName         = $content['lastName'];
$user->newPassword      = $content['password'];
$user->pending          = true;

$success = craft()->users->saveUser($user);

if ($success) {
    craft()->search->indexElementAttributes($user);

    // Assign them to the default user group
    craft()->userGroups->assignUserToDefaultGroup($user);

    // Send the activation email
    craft()->users->sendActivationEmail($user);

    // Update the Element Index
    craft()->search->indexElementAttributes($user);
}

For anyone's future benefit - this happens due to the fact I'm adding the user in the sproutForms.saveEntry hook. That happens after it messes around with the fieldContext and contentTable options for the Entry. As such, the user is getting saved to the wrong context, so it won't appear...

A quick workaround for this is to move the following lines in SproutForms_EntriesService.php:133-135 to lines 120. This resets the field context back before the hook is called.

if ($transaction !== null)
{
    $transaction->commit();

    SproutFormsPlugin::log('Transaction committed');
}

// Reset our field context and content table to what they were previously
craft()->content->fieldContext = $oldFieldContext;
craft()->content->contentTable = $oldContentTable;

Craft::import('plugins.sproutforms.events.SproutForms_OnSaveEntryEvent');

$event = new SproutForms_OnSaveEntryEvent(
    $this, array(
        'entry'      => $entry,
        'isNewEntry' => $isNewEntry,
        'event'      => 'saveEntry',
        'entity'     => $entry,
    )
);

craft()->sproutForms->onSaveEntry($event);


Creating a slideshow with dots navigation I have this slideshow implementing to entries, which works except Dot navigation.

A count of Dots in navigations depends on manually inputing attributes and assigning
numbers from 0...∞ ascendingly like this.

Actually, I limit(3) count of entries, so I know that there will be a certain number of dots. However, If there aren't any entries defined or only 1 entry defined, than I always get all three dots appeared, which don't function. So there MUST to be the exact number of dots as entries.

1 Entry: 1 Dot
2 Entires: 2 Dots
3 Entries: 3 Dots

So I'm thinking to go with if condition or loop through entries, but with my attribute output with number increased by 1.

So far, I've started with if, because no need to loop ... and I don't know, if this is right way.

{# Display navigation if the condition is true #}
{% if craft.entries.section('handle').lightswitchHandle('1') is defined %}

{# This is where I end up ... some comparission filter maybe ? #}
{% if craft.entries.section('handle').lightswitchHandle('1') %}

{% elseif craft.entries.section('handle').lightswitchHandle('1') %}

{% endif %}

{% endif %}

Update

    p
    n

    {# Get the slides, store in variable called "slides" #}
    {% set slides = craft.entries.section('food').news('1').limit(3) %}

    {% if slides %}

        {# Output slides, using the same "slides" variable #}
        {# Loop through "news" with lightswitch on #}
        {% for slide in slides %}
            {# Entry type - Article #}
            {% if slides.type == 'article' %}
                {% include '_includes/components/food/news-article' %}
            {# Entry type - Person #}
            {% elseif slides.type == 'person' %}
                {% include '_includes/components/food/news-person' %}
            {# Entry type - Recipe #}
            {% elseif slides.type == 'recipe' %}
                {% include '_includes/components/food/news-recipe' %}
            {% endif %}
            {% else %}

Any Text

        {% endfor %}

    {% endif %}

{% if craft.entries.section('food').news('1') is defined %}
{# Output navigation, check length of "slides" variable #}

     {% for i in 1..slides | length %}

     {% endfor %}

{% endif %}

First, store your slides in a variable when you fetch them using craft.entries. Then, you can use the length property of that variable (which will be equal to the number of slides) to output your dots/navigation.

Full example:

{# Get the slides, store in variable called "slides" #}
{% set slides = craft.entries.section( 'yourSlideSection' ).limit( 3 ) %}

{% if slides %}

    {# Output slides, using the same "slides" variable #}
    {% for slide in slides %}

[Your slide content here]

    {% endfor %}

    {% if craft.entries.section('handle').lightswitchHandle('1') is defined %}
    {# Output navigation, check length of "slides" variable #}

         {% for i in 0..slides | length - 1 %}

         {% endfor %}

    {% endif %}

{% endif %}

What the inner navigation loop does here, is to increment the variable i by one, each time the loop runs, until i is equal to the number of slides (slides | length). This means you'll always have exactly the same number of dots as slides. Inside the loop, the variable i is also used for the data attribute.

More on the Twig loop function here


Commerce: How to implement/save 'Use shipping for billing' field for future orders There is a 'Use shipping for billing' field in the Craft Commerce sample templates but it is unclear to me how to use that in the CP or for an account user in their account or for a future checkout.

I cannot find any documentation regarding this field in the Commerce documents. Is this only being used on the sample templates to handle front end display logic?

We want to be able to save this field so that when an account holder logs into their account, we can show their Shipping and Billing address in the correct state (ie. Billing address fields hidden and 'use shipping' checked). This would also apply to future checkouts too.

Is there a way to do this with the Commerce address fields? Or would we have to add a non-Commerce custom field to Users to save this and then add logic accordingly based on that field? And if yes, would that mean a separate ajax post to save that non-Commerce field during a checkout - or would it get saved to the User profile along with everything else?

We achieve this by simply checking the ids of the addresses set on the cart.  Commerce saves the last used shipping and billing address for customers, so you can just use some simple template logic to achieve what you want I think:

        {% set sameAddress = true %}
        {% if cart.shippingAddress and cart.billingAddress %}
            {% if cart.shippingAddress.id != cart.billingAddress.id %}
                {% set sameAddress = false %}
            {% endif %}
        {% endif %}

        <div class="same-address-checkbox">
            {{ forms.inputCheckbox({
                type: 'checkbox',
                id: 'sameAddress',
                name: 'sameAddress',
                checked: sameAddress,
                value: '1',
                label: 'Use same address for billing address?',
            }) }}
        </div>

One caveat here, if you offer a checkout during registration, you'llw ant to use my plugin for this as otherwise these last used addresses are not copied to the newly created Craft user - https://github.com/bossanova808/CommerceRegisterOnCheckout


How to paginate search results? What’s the best way to paginate search results?

I was using

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

and then

{% paginate craft.entries.search(query).section('…').limit(…).order('…') as entries %}

but the pagination links (paginate.prevUrl and paginate.nextUrl) don’t contain the query.

{{ paginate.nextUrl }}?q={{ query }} did the trick with this setup.


Rich Text Field Adding Tags around script I'm trying to add some embed code/script and the rich text field on save puts misc <p> tags around my code.

How do I save code so it keeps it's code formatting without adding an extra stuff?

You probably need to set the Redactor allowedTags config setting to allow <script> tags.

You can see how to define custom Redactor configs in Craft here.


Update search index after assets.onSaveAsset Event I use an assets.onSaveAsset Event in my plugin to update a field with the IPTC-Data of the image.

  $asset->getContent()->keywords = $this->get_iptc_keywords($imgPath);
  craft()->elements->saveElement($asset);

It updates the field values of the asset, but it does not update the search index. When i resave the asset, the searchindex table is updatet and works. Is this a craft bug and is there a craft way to update the search index for a single element (not the full index). Otherwise do i need to update the index by writing plain sql update/insert statements? Thanks for any help...

You could try and listen to onBeforeSaveAsset events instead of onSaveAsset. With onBeforeSaveAsset you can modify the asset model before being saved, so you don't have to do that manually.


Exporting Entry content I really spend a lot of time searching for a solution to this problem.  When I try using the Export plugin to export some entries with some Matrix fields and Neo fields for content, all that I can get is empty.

Seems to me that no one could've resolved the problem "Exporting / Importing all translatable Textfields of all entries in a section" or "How to export client-entered content for a specific channel to keep my local database in sync with staging" which my problem is similar to.  I tried to search in the database for the content of the entry added by the client, found it and I'm working on how to replace it in my DB without causing errors, but the relation between tables still confuses me.

So my questions are, is there any solution yet? If not do I need to create a plugin that read Matrix fields and export it as JSON data? Do I continue in my attempts in the database to try and find the entries and their related content (is it possible)?

I hope I have explained enough clearly my situation.

P.S : I'm still a novice in Craft CMS so take it easy on me ^^

Maybe check out the Sprout Reports plugin? I've used it to export matrix field data.


Use different template for same route based on user group I'd like to have consistent URL's for an account section but depending on the current users group, the template will be different. I know I could use the same template but there would be a lot of if/else's throughout and I'd like to avoid that.

URL pattern would be something like this:

If customer group
'account/settings' => '_dashboard/customer/settings'

If admin group
'account/settings' => '_dashboard/admin/settings'

I was thinking this might be possible with a plugin controller that each route would hit and then decide which template to render.

For both groups
'account/settings' => ['action' => 'action/path']

function action()
{
   // Get user
   // Set path based on user group
   // Set template path to front end
   // Render template
}

Can you see any problems with the above solution? Will there be much of a performance hit? Is there a better way?

Just do it with Twig by having a main template pull from two other templates based on the user group. So in your index template (or whatever template gets called), just add this at the top:

{% if currentUser.isInGroup('customer') %}
    {% include '_dashboard/customer/settings' %}
{% else %}
    {% include '_dashboard/admin/settings' %}
{% endif %}

And then fill out each template however you want.

Conversely, you can check if the user is a CMS admin with {% if currentUser.admin %} and then the {% else %} would be for customers.


How do I remove the index.php from all URLS in Craft 2 CMS? I am very new to Craft and have only been working with it for a few hours. However, I am stuck with something I can't seem to figure out.

I understand the basics of templates, of which I have an index.php using % extends "_layout" % Then I created a new Section with the Section Type set as Single for About. Craft sets the Entry template to about and I have the URL set to be about. Then I create a new template file called about.html.

However, the problem comes when I go to view it on localhost/about as I get the following message;

The requested URL /about was not found on this server.

But when I navigate to index.php/about it is there. I'm confused as to why the architecture of the URL is set up this way as on a normal website you would'nt have index.php/ before every other page on your site.

Is this fixable?

It sounds like you haven't set up your .htaccess file or have failed to rename it. The file in the default set up doesn't have the . at the start.

Read https://docs.craftcms.com/v2/installing.html carefully. The bit concerning htaccess is just before step 2.

Also ensure you're files are in the right place.


Check which pagination page to display code outside of pagination loop I have some Featured news entries which appear at the top of the rest of the news entries.

How do I set this so they are only on page 1 (before any pagination pages)?

{# Only show on page 1 of pagination #}

   {% for entry in craft.entries.section('newsEvents').highlightNews('1').limit(2) %}

     {% if entry.listingImage|length %}
    {% for image in entry.listingImage %}

    {% endfor %}

    {% endif %}

{# End only show on page 1 of pagination #}

{% paginate craft.entries.section('newsEvents').limit(12) as entriesOnPage %}

  {% for entry in entriesOnPage %}

    ...

  {% endfor %}

{% if paginate.totalPages > 1 %}

{% set pagination = true %}

    {% if paginate.prevUrl %}
&#171;
{% endif %}

    {% for page, url in paginate.getPrevUrls(5) %}

{{ page }}

    {% endfor %}

{{ paginate.currentPage }}

    {% for page, url in paginate.getNextUrls(5) %}

{{ page }}

    {% endfor %}

    {% if paginate.nextUrl %}
&#187;
{% endif %}

{% endif %}

UPDATED/EDIT ANSWER:

If you only want to show the entries on the first page you should make an if statement to check if you are on the first page for your Featured Items by requesting the page number.

Option 1:

{% if craft.request.getPageNum() == 1 %}

// Featured content here

{% endif %}

Option 2:

{% if craft.request.getLastSegment() == 'p1' %}

// Featured content here

{% endif %}

The first option is the best / cleanest solution even though they give the same outcome. Option 2 is a nice work around but might be more usefull in other ways then this one.

More about craft requests can be found in the docs:
https://craftcms.com/docs/templating/craft.request


Upload file from plugin's Controller to a non-Assets folder I have a plugin Controller that accepts a POSTed form, including an uploaded file. If I make an Assets Source I can successfully save the file into its folder like this:

$file = UploadedFile::getInstanceByName('myFieldName');

$folder = craft()->assets->findFolder(array(
    'sourceId' => 3, // My Asset Source's ID.
));

$response = craft()->assets->insertFileByLocalPath(
    $file->getTempName(), // Local path to file.
    $file->getName(), // Name file should be given when saved.
    $folder->id,
    AssetConflictResolution::KeepBoth
);

if ($response->isSuccess()) {
    ...

However, I want to upload the file to a folder that's not an Asset Source - for security reasons I don't want these particular files to be visible in any way in the CMS. Is there a way to do this, eg, by using a filepath rather than an Asset Source?

(I'm also not sure how to validate the file, in terms of its file extension, size, etc. I can see how to do this in Yii but I'm not sure how to do it having uploaded the file as above.)

Ahh, a bit of fiddling and poking around later...

$file = UploadedFile::getInstanceByName('myFieldName');
$fileName = AssetsHelper::cleanAssetName($file->getName());

// Make fileName uniqueish by adding a timestamp to it.
$fileParts = explode(".", $fileName);
$extension = array_pop($fileParts);
$fileName = join(".", $fileParts) .'_'. time() .'.'. $extension;

$filePath = '/path/to/my/folder/' . $fileName;

$response = $file->saveAs($filePath);

Seems to work OK!

The unique filename stuff seems not entirely great. Might be better to see if the file exists first, and if so, make a new name.

Just need to work out how to validate my Model now...

UPDATE: Oh, that was quick. So now I do:

$post = craft()->request->getPost();
$myModel = MyForm_FilesModel::populateModel($post);

// All the file-handling stuff as above.

$myModel->myAttribute = $file;

if ($myModel->validate()) {
    ...

Where my model is something like:

<?php
namespace Craft;

class MyForm_FilesModel extends BaseModel
{
    protected function defineAttributes()
    {
        return array(
            'myAttribute' => array(AttributeType::Name),
        );
    }

    public function rules()
    {
        return array(
            array('UploadPassport', 'file',
            'allowEmpty' => false,
            'maxFiles' => 1,
            'maxSize' => 5 * 1000000, // 5MB
            'tooLarge' => 'Sorry, the maximum file size is 5MB',
            'types' => array('jpg', 'png', 'pdf'),
            'wrongType' => 'Files must be one of jpg, png or pdf',
            'message' => 'Please upload a file'),
        );
    }
}

(The defineAttributes() stuff feels very wrong, as this isn't a proper Craft model - I'm not saving any of this as an Entry etc defined in the Craft Admin. But I can't see how else to make this stuff work.)


What are the best practices for using the {% cache %} tag? I started using the {% cache %} tag and would like to know what the best practices are:

.

Regarding performance:

For example does it make sense..

..to cache the whole template, or is it better to enclose each query separately?
..to combine the cache-tag with other supported caches?
..to cache non-dynamic content?

.

Regarding development:

I saw the tip to use: {% cache unless craft.config.devMode %}. Is there anything else to consider during development?

Generally you’ll just want to cache areas of your templates that are going to trigger a lot of database queries, or fetch a lot of data, since those are going to have the biggest hit on your site’s performance. Matrix field loops that have relationship fields inside them (Entries/Assets/etc.) are a good example, since each Matrix block is going to come with one or more DB queries.

There’s not much advantage to caching less intensive areas of your templates, and might lead to unexpected consequences, if you have anything dynamic being output that’s not pure-content, such as the logged in user’s username.

  ..to combine the cache-tag with other supported caches?

Worth mentioning that template caching does not respect the cacheMethod setting – that’s just for data caches. Template caches always go to the database, which in this case is the most performant option.


Programmatically Login From Plugin I'm writing an LDAP authentication plugin, which, if the authentication matches, will log the user into a 'general' username/password, in order to view a protected page.  The 'general' username/password is part of a usergroup with restricted priveleges.

In my plugin, in the controller file, I have this:

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

with the $username and $password variables set just above that.  However, the login process does not appear to be happening, as my check in my template is not displaying the username:

{% if currentUser %}
Welcome, {{ currentUser.friendlyName }}!
{% endif %}

However, when I log on as that 'general' username/password, from the login page, and then refresh my template, it does show that the login for that profile has successfully occurred.

What may need to be done to effect a successful login, in the plugin?
Thanks!

If you want to login a user, you need to use the login function

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


Is there some way to create sections inside static translations? (craft v3) At the moment I'm converting a website from a different CMS to Craft v3. The 'old' CMS had a convenient way to set a hierarchy for static translations in yaml files so that we could split translations into groups per section on the website.

Like this:

  PageNavigation:
    PrevPage: 'Previous'
    NextPage: 'Next'
    GotoPrevPage: "Goto previous page: '{prevPageTitle}'"

Now I can't find anything like that on the documentation and google search on Craft CMS. At the moment this is what I got instead:

<?php

return array(
    'PageNavigation.PrevPage' => 'Previous',
    'PageNavigation.NextPage'=> 'Next'
    'PageNavigation.GotoPrevPage' => "Goto previous page: '{prevPageTitle}'"
);

So every translation-item has a group supplied to it as a prefix, followed by a dot and then the translation-itemID. But this gets ugly soon and is not as convinient as what I was used to in the other CMS.

1)
Does anybody here perhaps knows if CraftCMS has a better way of setting hierarchy to static translations? So to group translation items to sections/elements on the website?

2)
Is there a way in Craft CMS to have a placeholder inside the translation-string being replaced by a variable inside the template?

In the 'old' CMS I could replace a placeholder like {placeholder} inside a translation-string by a dynamic variable inside the template. So a translation string like "Goto previous page: '{prevPageTitle}'" would come out as "Goto previous page: 'all about craft blog title'". Is there some functionality build in Craft that could replace a placeholder in the translation-string by a dynamic string?

Thanks in advance!!

You can include custom translation categories within your config/app.php

return [
    'modules' => [
        'my-module' => \modules\Module::class,
    ],
    'components'    => [
        'i18n' => [
            'translations' => [
                'foo'  => [
                    'class'            => \craft\i18n\PhpMessageSource::class,
                    'forceTranslation' => true,
                    'basePath'         => '@translations',
                ],
            ]
        ]
    ]
    //'bootstrap' => ['my-module'],
];

This will include the custom group foo to your app, make sure to change the basePath variable to a path you like

That being said your folder structure will look like

-your base path
|-- en-US
|-----> foo.php
|-- de-DE
|-----> foo.php

within these files you can create your custom translations

return [
    'foo' => 'bar'
];

{{ 'foo'|t('foo') }} -> will now display bar
{{ 'foo'|t('site') }} -> will still show foo


Stripe checkout, card declined but no frontend error I have a Craft 2 site running commerce who have a small issue with the stripe gateway.

I am using https://checkout.stripe.com/checkout.js instead of the standard stripe markup.

JS looks like this (inside the standard commerce/payments/pay form:

var handler = StripeCheckout.configure({
    key: '{{ cart.paymentMethod.settings.publishableKey ?? '' }}',
    image: '',
    locale: 'auto',
    token: function(token) {
        // You can access the token ID with `token.id`.
        var stripeToken = token.id;
        // Get the token ID to your server-side code for use.
        document.getElementById('stripe-token').value = stripeToken;
        document.getElementById('payment-form').submit();
    }
});

document.getElementById('paymentButton').addEventListener('click', function(evt) {
    // Open Checkout with further options:
    handler.open({
        name: '{{ siteName }}',
        email: '{{ cart.email }}',
        currency: '{{ cart.paymentCurrency }}',
        description: 'Membership',
        amount: {{ cart.totalPrice|commerceCurrency(cart.paymentCurrency,convert=true,format=false) * 100 }}
    });
    evt.preventDefault();
});

// Close Checkout on page navigation:
window.addEventListener('popstate', function() {
    handler.close();
});

Currently, in some cases, the card is declined, but the popup from stripe acts as if everything is ok. You get a green check-mark when submitting, and then the checkout page just reloads instead of going to the order overview.

I am looking on network and console in Chrome, and cant see any responses or error messages. And in the basic checkout page from commerce I dont see any error array for the payment gateway.

Am I missing something? On test mode I can reproduce this using card number 4000000000000341. The cart looks like this in the CP:

Usually when the card gets declined there is a notification in the stripe popup. But not in this case. And as you can see from the picture Craft is well aware that the payment got declined. Is there any way for me to notify the customer of this? Instead of just having the checkout page reload?

As usual it is just me being stupid.
The error is accessible with:

{% set error = craft.session.getFlash('error') %}
{{ error }}

Maybe it will help some other people.


Craft Commerce: make address phone telephone field required without JavaScript Because I used a similar address model to the one supplied in the Craft Commerce templates, which essentially uses the same form partials for both address and billing, and also hides and shows the form using JavaScript, I can't use HTML required attributes.

Is there an easy way to add in the config files a way to make 'shipping.phone' required and return an error in the same way the default required fields work?

Contact details

        <input type="text" id="{{ modelName }}-phone" class="u-full-width" name="{{ modelName }}[phone]" value="{{ model ? model.phone : '' }}">

        Telephone number
        {% if model and model.hasErrors('phone') %}{{ model.getError('phone') }}{% else %}Required{% endif %}

In case we need to contact you about important details regarding your order.

The way to do address validation with Commerce in gneral is using a plugin and listening to the onBeforeSaveAddress event.

Set up a listener with something like this:

    craft()->on('commerce_addresses.onBeforeSaveAddress',
        [
            craft()->businessLogic_logic,
            'onBeforeSaveAddressHandler'
        ]
    );

And here's an example of a function that does some validation:

public function onBeforeSaveAddressHandler($event){

    $address = $event->params['address'];

    if(!$address->firstName){
        $address->addError('firstName','First name must not be empty');
        $event->performAction = false;
    }
    if(!$address->lastName){
        $address->addError('lastName','Last name must not be empty');
        $event->performAction = false;
    }
    if(!$address->phone){
        $address->addError('phone','Phone number must not be empty');
        $event->performAction = false;
    }
    if(!$address->address1){
        $address->addError('address1','Street Address line 1 must not be empty');
        $event->performAction = false;
    }
    if(!$address->city){
        $address->addError('city','Suburb must not be empty');
        $event->performAction = false;
    }
    if(!$address->zipCode){
        $address->addError('zipCode','Postcode must not be empty');
        $event->performAction = false;
    }
    if(!$address->countryId){
        $address->addError('countryId','Country ID must not be empty');
        $event->performAction = false;
    }
}


Charge plugin: custom actions on webhooks I'm trying to integrate Charge with Craft Commerce.

Basically I need to

a) use Stripe to set up subscription for the amount based on what's in the cart (this seems to be possible out-of-the-box)

b) on successful charge - mark order as complete (I think I can use 'charge.onCharge' event here)

c) listen to webhooks - when the next recurring payment succeeds or fails, make change to order.

Is there a way to write custom action for (c) without hacking into Charge core?

I see there is Charge_Actions service fireing some events, but how do I reference/listen to those actions in a custom plugin that I create?

I don't see events being triggered in the Actions Service (in my version of Charge anyway), so you won't be able to listen for those. You'll most likely have to modify the core, if you do, document that and when you update charge, you can easily put your modifications back into place or do a pull request to charge in hopes that event gets added to the core.


How to create a relation to multiple assets in my Plugin Model/Record? I defined an estateRecord in my Plugin. Every estate has a set of images that i want to import from a zip file directly via assetsService::insertFileByLocalPath().

In my estateRecord I defined a relation:

public function defineRelations()
{
    return array(
        'assets' => array(static::HAS_MANY, 'AssetFileRecord', 'id'),
    );
}

Is that correct?

Now i'm stuck to define a 'asset'-field in the estateModel to access the image-sets.

I just find a solution to define the Attribute for one assetId but have no idea how to define the Attribute for the related set of assetIds.
How can i do this?

I think what you're asking is how to define the relationship using Active Record in the other direction - going from Craft's AssetFileRecord to your plugin's EstateRecord.

And the answer is that you can't without hacking the AssetFileRecord and manually adding a BELONGS_TO relation back to your Estate Record.

You're going to be much better off ditching records and active record for this all-together, I think.  Have your service layer use the Query Builder craft()->db->createCommand() directly, then you can join in any data you want from any tables outside of the context of active record.


Multiple authors for an entry The website I'm currently working on is a plattform where several 'subgroups' can post events but also have their own subpage. So the two affected secrions are 'event' and 'subgroup'.
Currently, every subgroup has an account which is author of their entry and they can create new event entries (which are linked through an entry field).

I'm wondering if it's possible to have multiple accounts for a subgroup which have the permission to edit their entries but not the ones of other subgroups.

Long story short: is it somehow possible to assign an entry multiple authors?

We solved it like this...

We created a Users field called “Article Authors”, for that Articles section. And there unlimited users could be selected as “Authors” of the entry (for search results, relatedTo, etc...). Each article typically multiple authors.

But we assigned only 1 author as the only one with real editorial access, as the “owner”, so: basic Craft behavior.

We thought this would be limiting, but actually it turns out, in practice, it’s pretty good to have only 1 person in-charge with end-responsability. It’s clear where it lies, and he/she will communicate with the team before changing things. This: in contrast with 5 authors being able to acccess and edit an article, which we thought would be a good plan, but in reality isn’t. This forces them to communication amongst themselves and it’s clear who’s responsible.

Plus with the custom Users field, you basically maintain all functionality you want related to the entry.

We have about 250 articles now running with over +1500 author members, and have not got any complaints.


List all entries below top level 1 in a structure section (level 2 or 3 or 4 ...) I have a structure section with 3 levels.
I d like to list all entries below 1st level.
I see ancestorDist or descendantDist but I m not sure it is what I need...
https://craftcms.com/docs/templating/craft.entries

I see I can select multiple levels:
{% set entries = craft.entries.section('library').limit(10).level(2,3) %}
but I d like something like:
{% set entries = craft.entries.section('library').limit(10).level(>1) %}

Alright. you can just exclude the top level entries with not:

{% set entries = craft.entries.section('library').level('not 1') %}


Check if the first block in a Matrix field matches one of an array of types I need to check if the first block in a Matrix field matches one of an array of types. Here's a simplified version of my code:

{% if entry.newsArticleContent.one().type in ['fullWidthImage', 'imageGroup'] %}
    yep
{% else %}
    nope
{% endif %}

{{ entry.newsArticleContent.one().type }} outputs fullWidthImage, but the above conditional outputs nope.

The following outputs yep:

{% if 'fullWidthImage' in ['fullWidthImage', 'imageGroup'] %}
    yep
{% else %}
    nope
{% endif %}

so I know it's not a problem with the if statement or the fact that I'm checking the value against an array.

Is there a reason why the value of entry.newsArticleContent.one().type can't be used in this context?

Thanks!

EDIT: Thought I should mention that I'm looping through all blocks in the Matrix field later on in the same template. Just in case that's relevant.

When you call entry.newsArticleContent.one().type, what you're getting is an instance of craft\models\MatrixBlockType (https://github.com/craftcms/cms/blob/develop/src/models/MatrixBlockType.php)

It just happens to have a __toString() method that will print out the handle when it's requested, but the if comparison you're doing is using the entire MatrixBlockType instance.

What you're looking for is:

{% if entry.newsArticleContent.one().type.handle  in ['fullWidthImage', 'imageGroup'] %}


Display Matrix block field base on location of query supportContent is a Matrix field
contentBlock is a Matrix block
heading and body are fields within contentBlock

I am trying to display block.heading only if my query is in the block.body

{% for block in entry.supportContent.type('contentBlock') if query in block.body  %}
    <h3>{{ block.heading }}</h3>
{% endfor %}

This code is not working. Any help?

Your code would work as-is if block.body was a Plain Text field.

But since it's a Rich Text field, it technically returns a RichTextData object and Twig's in operator doesn't know what to do with objects.

This will grab the string data from the Rich Text field so in operates as you'd expect.

{% for block in entry.supportContent.type('contentBlock') if query in block.body.getRawContent()  %}
    <h3>{{ block.heading }}</h3>
{% endfor %}


Resource for setting up Craft CMS Fields It's a good 7 months after the last time this question was asked. I've been developing sites for a long time, expert with Wordpress, some Drupal, Joomla when forced. I can understand a good part of Craft but there really isn't the basic tutorial you'd generally see with other software that gives you an idea how to construct a site. The Happy Lager demo is more of a very quick showcase of how neat CraftCMS can be but it doesn't really go into just the very basics, like setting up fields properly.

I have seen the sparse resources. The paid video, which includes how to install the software, is not an option. Is there still nothing that does a reasonable job of just running through the process and approach to setting up a basic site using the system? In addition, are there any resource repositories, e.g. plugins, etc. so you don't need to reinvent everything? Thank you.

This is a brain dump of learning resources I can think of.

There's the official documentation.
Straight Up Craft has some great learning articles and tutorials.
They also happen to have the most comprehensive list of Craft plugins until the official plugin store becomes a thing.
The Craft site also has help articles and tutorials.
The online Craft demo site running Happy Lager.
The Happy Lager repo if you'd prefer to setup locally.
This Craft Stack Exchange site for Q&A.
The Craft Slack group with people on from around the world practically 24x7.
The Craft feedback site to see if a feature you'd like to ask for has already been asked.
Sites like Craft Cookbook for help with Twig and templating recipes.
Twig's documentation for more Twig help.
Mijingo has many Craft-specific video tutorials both free and commercial. Also, there are articles and more.
There are many user generated Craft video tutorials up on YouTube.
craftlinklist.com is a periodic newsletter where you can sign up for a curated list of Craft resources from around the web.


How can I know the discounts available to a product before adding it to the cart? How do I show possible discounts available to the current product?

You currently can not know if a product matches a discount until it is added to the cart and the discount engine does the checks based on the full conditions of the discount. Many conditions of which are directly related to the product being in the cart. For example a minimum order qty.

But if you want to return a possible list of discounts to show the custom of which the product MAY be eligible before adding to the cart then you can do something like this:

{% for discount in craft.commerce.discounts %}
  Possible Discounts:

  {% if product.id in discount.productIds or product.typeId in discount.productTypeIds %}
    {{discount.description}}

  {% endif%}
{% endfor %}

This only checks the product and it's product type is explicitly listed in the discount, but you can add additional conditions if you wished.

It is recommended the discount description has a readable sentance for how this discount could be applied. For example:

  Buy 2 or more sneakers and get 75% off.


Sendmail not working on Craft 3 I'm building my first Craft 3 site, and having problems getting email to send. I've set it to use Sendmail but when I click the Test button in the CP, I get "There was an error testing your email settings".

I know Sendmail isn't the best option but I need something for now until we get something more robust in place. My client doesn't yet have any email set up for this domain, but I assume Sendmail should still be able to create email?

I've tried using Sendmail from the command line and that seems to work fine. For each attempt to test from the control panel, I get this error in web.log:

2018-08-20 10:02:55 [86.167.235.31][1][-][error][application] Error sending email: Expected response code 220 but got code "", with message ""

I'm on Craft 3.0.19. Any ideas what might be going wrong?

Most servers (speaking in generalities) won't send mail by themselves anymore. You'll need to use some sort of SMTP service.

Check out SendGrid to get you going. I believe they have a free plan. You can choose SMTP from the mail options from the settings page.

Choose 'Use Authentication' and from there your username is well, your username and your password is...your password. Use Port 587.

Hope this helps!


Installing other PHP app in sub directory My question is the opposite of this question: Installing Craft in sub directory

I have a Craft website and I need to put a Laravel application in a sub directory, it almost works. I have made the directory and created a symbolic link to the public folder for the Laravel application.

This works with the default route in Laravel but as soon as I try any nested routes I just get a Craft 404.

Is is possible to get Craft to completely ignore a folder or something, or do I need to figure out an alternative solution.

Thank you!

Yes, possible. You just need to override the URL routing within the subdirectory, so requests to /sub/* get routed to /sub/index.php rather than /index.php.

For example, if you’re using Apache, just place Laravel’s .htaccess file within your subdirectory.


Carousel with text using Matrix blocks I am trying to create a carousel where each slide will have a title, subtitle, and maybe a summary.

I know I can create a carousel like this with a set number of slides.
I would like to create one where if an image is added the subsequent fields(title, subtitle, and summary) would be made available for that slide. This way I could have as many slides as possible.

I believe this may be accomplishable with Neo since it allows me to go three layers deep into a matrix. Sadly due to the project constraints, we cannot use any Matrix plugins like Neo or Supertables.

Is there any other way to accomplish this without the use of a plugin.

Right now we are using Craft 2. If this is not possible in Craft 2 I would be interested to know if it would be possible in Craft 3.

Is this possible with the limitations set forth
How would this be accomplished

Old ticket, I know, but thought I'd answer.

Personally, I use a channel for carousel slides as clients for me have tended to mix and match them on multiple places on a site or stop using them then reusing them a few months later.

This way they have a pool of instances of reusable slides that won't disappear. Hopefully saving redoing work they've already done a few months prior.

If I've understood your question, I'd have a channel with two entry types. "Image slide" or "Text slide".

So when they add a new one they can choose if they want one with an image or just text.

Then depending on how you're constructing your pages you just need a Matrix component type that is named 'carousel' with an entries field with the slides channel selected as it's source or just an entries field on it's on in the page entry types you want this carousel to be. (I'd limit it to three or four for UX purposes).


Craft 3: how to call methods in another plugin's service? In Craft 2, we used to be able to do so by doing:

craft()->plugin1->myMethod();

from Plugin 2's service for example.

Now in Craft 3, I couldn't figure out a way to do it.

Plugin1::$plugin->myService->myMethod();

seems to only work within the Plugin 1's code base.

Assuming Plugin1 is their main plugin class file name, you could do:
\fully\qualified\namespace\Plugin1::getInstance()->myService->myMethod();

In order for this to work:

Craft must be installed.
Plugin1 must be installed and enabled in Craft.
Composer autoloading has to be working so that it knows where to find Plugin1

If you're doing this from a custom module, then you'll need to listen for the EVENT_INIT event, because plugins get instantiated after modules.
i.e.
Craft::$app->on(Application::EVENT_INIT, function() {
    \fully\qualified\namespace\Plugin1::getInstance()->myService->myMethod();
});


Can admin receive email notifications of new user registrations? I would've thought this would be core functionality, but does it require additional plugin functionality?

I believe you would need a plugin for this — but the plugin can be really basic. In your plugin's main file simply add an 'init' method that listens to the 'users.saverUser' event and checks the 'isNewUser' event attribute; then prepare and send your email.

The process is outlined in this answer that sends out an email to members of a userGroup when an entry is saved. Same principle would apply, just using users.saveUser instead.

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

    craft()->on('users.saveUser', function(Event $event)
    {
        $user = $event->params['user'];
        $isNewUser = $event->params['isNewUser'];

        if ($isNewUser) {
            // Send Mail
            $email = new EmailModel();
            $email->toEmail = "user@email.com;
            $email->subject = 'New User Registration';
            $email->body    = 'New User: '.$user->firstName.' '.$user->lastName;

            craft()->email->sendEmail($email);
        }

    });
}


Render Template issue I've got a plugin which am triggering emails from (listening to the users.onSaveUser event).

I am using a conditional to send two emails, depending on the permissions of the person registering the user.

In one instance am using $email->htmlBody = craft()->templates->render('emails/employee', $vars); which works fine.

However, in another instance am using $email->htmlBody = craft()->templates->render('emails/prospect', $vars); and getting the following error:

Unable to find the template “emails/prospect”.

Any ideas why this might be happening or how to get more useful feedback?
I have double and triple-checked the spelling of the files and they are indeed available in the file system:

The template path needs to include your plugin folder name. So in your case the path to your email templates would be pluginname/templates/emails/prospect and the path you pass to render() would be pluginname/emails/prospect.

More info: Plugin template paths explained

But that doesn't explain why the first template path appears to work.

I’d probably keep the templates inside my plugin if they weren’t being used from the front-end. However, if you'd like to change the default template path to your front-end template directory this answer will help.


How can I add custom headers to an ElementAPI response? I need to add the a custom header to the ElementAPI endpoints I setup but I want to avoid editing the source of the plugin. What is the best way to go about this?

The ElementAPI plugin returns some default headers by using:

JsonHelper::sendJsonHeaders()

To quickly achieve what I needed I added the following to the ElementApiControllor.php:

HeaderHelper::setHeader(['Surrogate-Control: max-age=300'])

This works for now but I'd love to learn how to extend existing plugins that don't have any documented hooks with my own if it is possible.

You can do this by assigning your endpoint(s) to a function:

return [
    'endpoints' => [
        'my-endpoint' => function() {
            HeaderHelper::setHeader(['Surrogate-Control: max-age=300']);

            return [
                // ...
            ];
        }
    ]
];

UPDATE

Alternatively as of v1.2, you can do it from a separate plugin using the onBeforeSendData event:

public function init()
{
    craft()->on('elementApi.onBeforeSendData', function(Event $event) {
        HeaderHelper::setHeader(['Surrogate-Control: max-age=300']);
    });
}


How to redirect an entry's URL to a specific URL? Say I have a custom field "URL" for each entry and I want them to be redirected to these specific URLs instead of Craft's.

Similar to WordPress "Page Links To" plugin. http://wordpress.org/plugins/page-links-to/

Can I do this in Craft?

Instead of using a redirect, what about using the saved URLs directly with your links?

Let's say it's a channel with the handle myExternalLinks where you collect the links. The actual URL is entered into a field with the handle myLinkUrl.

This is the template code to list the links:

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

{% for link in links %}

    {#
     # Link to the URL entered into `myLinkUrl` instead of
     # linking to `entry.getUrl()` and then using a redirect on that entry template
     #}
    {{ link.title }}

{% endfor %}


Amending a lightswitch field value inside a matrix, from a plugin? I have a plugin which is used to send a notification email when certain events happen.

I need to watch the contents of a Matrix field attached to a User, and when a Lightswitch field inside the Matrix is 'on', flip another Lightswitch field on the same matrix block. Here's the simplified code I have so far:

craft()->on('users.onBeforeSaveUser', function(Event $event) {
    foreach ($user->getContent()->myMatrixField as $matrixBlock) {
        if($matrixBlock->firstLightswitch){
            $matrixBlock->secondLightswitch = '1';
        }
    }
}

I am getting the following error though:

  Property “Craft\MatrixBlockModel.secondLightswitch” is not defined

It's very definitely defined. I presume I'm trying to set the field incorrectly, but can't find out how.

You have to do:

$matrixBlock->getContent()->setAttribute('secondLightswitch', '1');

You can only get attributes via magic methods but you can't set them


Environment specific siteUrl settings not working I followed the advice from this and this post, but I just can't get my environment specific siteUrls to work.
This is what my config file looks like:
return array(

    '*' => array(
      'errorTemplatePrefix' => "pages/",
    ),

    '.dev' => array(
      'environmentVariables' => array(
        'userSessionDuration' => false,
        'devMode' => true,
        'siteUrl ' => 'http://myurl.dev',
      )
    ),

    '.com' => array(
      'environmentVariables' => array(
        'userSessionDuration' => false,
        'devMode' => true,
        'siteUrl ' => 'http://myurl.com',
      )
    ),

    '.org' => array(
      'environmentVariables' => array(
        'siteUrl'  => 'http://myurl.org',
      )
    )
);

These do not take precedence over any URL specified in Settings > General in the CP as outlined in the docs. If I set the Site URL field to {siteUrl} in the CP, then my links are broken and look like this: {siteUrl}/link-to-a-page.
Am I missing something else to get the siteUrl settings to work?

Update
Fixed the additional space in 'siteUrl ', thanks to Lindsey.
My config settings now look like this:
'*' => array(
  'errorTemplatePrefix' => "pages/",
),
// local
'.dev' => array(
  'devMode' => true,
  'userSessionDuration' => false,
  'environmentVariables' => array(
    'siteUrl' => 'http://myurl.dev',
  )
),
// staging
'.com' => array(
  'devMode' => true,
  'userSessionDuration' => false,
  'environmentVariables' => array(
    'siteUrl' => 'http://myurl.com',
  )
),
// live
'.org' => array(
  'environmentVariables' => array(
    'siteUrl'  => 'http://myurl.org',
  )
)

With this and adding {siteUrl} in the CP, everything works as expected - hooray!
It does however not reflect what the Craft docs say, as they state that the config settings "will take precedence over the Site URL setting in Settings → General". I've contacted the Craft team to let them know about this.

Update #2
Got this response from Brandon:

“I'm guessing that when you added 'siteUrl' to your config, you put it inside the environmentVariables array? (which would explain why adding {siteUrl} to the CP setting made it work.)
When the documentation is referring to the siteUrl config setting, it's referring to an actual top-level config setting, not some custom "siteUrl" environmentVariable that happens to have the same name.”

So I've taken the setting out of environmentVariables, and hey presto, it all works as expected. You even get a helpful message in the CP:

Final working code:
'*' => array(
  'errorTemplatePrefix' => "pages/",
),
// local
'.dev' => array(
  'devMode' => true,
  'userSessionDuration' => false,
  'siteUrl' => 'http://myurl.dev',
),
// staging
'.com' => array(
  'devMode' => true,
  'userSessionDuration' => false,
  'siteUrl' => 'http://myurl.com',
),
// live
'.org' => array(
  'siteUrl'  => 'http://myurl.org',
)

Got there in the end - phew!

Make sure that you change .dev, .com, etc. to reflect your actual environment URLs. They operate based on a partial string match, so as long as your URL contains one of those substrings, it'll pick up the first one it matches.

For example:

'local.mywebsite' => array(
  'environmentVariables' => array(
    'userSessionDuration' => false,
    'devMode' => true,
    'siteUrl ' => 'http://local.mywebsite',
  )
),

'mywebsite.com' => array(
  'environmentVariables' => array(
    'userSessionDuration' => false,
    'devMode' => true,
    'siteUrl ' => 'http://mywebsite.com',
  )
),

UPDATE

Whoa, I think I may have just realized what the problem is... I copied my example from your original code, and copied a glitch right along with it...

You've listed siteUrl like this:

    'siteUrl ' => 'http://mywebsite.com'

Notice anything? There is an extra space between siteUrl and the closing quote.

    'siteUrl '

... should be:

    'siteUrl'


Grouping Super Table Results via Twig Multidimensional Array I'm trying to loop through a Super Table array and group results based on a category ('contribution'). I've gotten pretty far but I'm struggling creating an array in Twig that gives me what I need (I find associative arrays very cumbersome in Twig after using PHP for so long...).
Setting the contribution works. I just can't seem to write the merge rule correctly so each contributor merges into their respective role. The next step would to then join together the list of names for further output...
Here is where I am currently stuck:
  {% set featuredContributors = [] %}

  {% for person in book.contributors.all() %}
    {% if person.featured == 1 %}
      {% set contribution = person.contribution.one().title %}
      {% set contributor = person.contributor.one().title %}
      {% set featuredContributors =
        featuredContributors |
          merge({
          (contribution): [contributor]
          })
      %}
    {% endif %}
  {% endfor %}

The resulting array should look like (with each array joined as a comma separated list):
{% set featuredContributors = {
  Editor: 'Person One, Person Two',
  Writer: 'Person Three, Person Four',
  Other Role: 'Person Five',
} %}

Is there an easier way to do this? PHP via a Twig Extension? :D

For grouping arrays, use Craft's group filter or index filter, then for joining the array items with commas use Twig's join filter.
Something like this might be what you're looking for (I've also added eager loading for improved performance, and I used the map filter as a cleaner way of organising the array, though you could use a nested loop if you find it easier to read):
{% set featuredPeopleGrouped = book.contributors
    .featured(1)
    .with(['contribution','contributor'])
    .all()|group('contribution[0]')
%}

<dl>
    {% for contributionType, rowData in featuredPeopleGrouped %}
        {% set contributors = rowData|map(row => row.contributor[0].title) %}
        <dt>{{ contributionType }}: </dt>
        <dd>{{ contributors|join(', ') }}</dd>
    {% endfor %}
</dl>


Limit by section in Weighted Search I'm using Weighted Search on a site and want to prevent the results from listing entries from certain sections.

Looking at the README.md suggests that this functionality has not been built into the plugin. However, does anyone have any experience of getting the plugin to only search in certain sections? Either through the {% set results %} OR tweaking the plugin?

I've tried added .section('mysection') to the {% set results %} but this seems to break the search.

// Working

{% set query = craft.request.getParam('q') %}
{% set results = craft.weightedSearch.substringSearch(query) %}

// Not working

{% set query = craft.request.getParam('q') %}
{% set results = craft.weightedSearch.substringSearch(query).section('mysection') %}

Hoping someone else has managed this and I don't have to go back to the standard Craft search.

Thanks

I've also seen this issue myself when using weightedsearch and as a result I have jsut gone and created a solution for this by adding a new parameter to the substringSearch function.

I've also commented on the issue which was raised back in January on the weightedsearch github page and added my updated files as a zip file, so please feel free to download it and give it a go if you wish. By putting it onto the issue tracker they will hopefully pull this feature into the plugin in a future release now.

You can see further details here: https://github.com/wja-no/craft-weighted-search/issues/1


High amount of API calls from Smart Map I have a Smart Map setup and installed it on a site.

The section averages 300 page views per day according to Google Analytics, but Google API is maxing out the 2500 requests on the free plan. I've bumped up to a paid plan, but does anyone know why there are so many requests?

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

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


Catch-all routes based on template structure I have many of the templates organized into sub-folders. E.g. /manager/entries/edit.html, /manager/users/edit.html etc.

The site is using 4-segment URLs to access code in those templates, e.g. http://site.com/manager/entries/edit/{slug}, http://site.com/manager/users/edit/{id} etc.

Currently I have to set up custom route for every template, e.g.     'manager/users/edit/(.*)'        => 'manager/users/edit', etc.

Is there a way I could set up a "generic" route which would first check for existing templates in a subfolder (whether globally or on per-folder basis) and try to use that first? So I would not need to create route for each individual template.

What we often do for a section (lets call it Pages) is actually not use any custom routing, and control things in the templates.

Start by setting the section template to pages/index. In your index.html file, we usually have the following:

{# Look for a template for this entry type (if any), then look for a template matching #}
{# the entry's slug, and fallback to the default '_entry' template #}

{% include [
    'pages/' ~ entry.type,
    'pages/' ~ entry.slug,
    'pages/_entry'
] %}

Using Twig's array-style include means it'll look for templates, and if one doesn't exist, move onto the next. In this scenario, we can simply create a file for an entry type, or even for a specific slug, with a fallback to a default.

Your case might be different of course, but might be a step in the right direction.


Is it possible/recommended to use Solspace Freeform for a front-end user login form? I would like to build a front-end user login form using Freeform. Is it possible or even recommended? Right now all my form input styling/markup lives inside the Freeform render templates and it would be nice to be able to use this for the login form, instead of manually using the provided example form here.

It’s potentially possible with a custom module, but it would be far less effort (not to mention, more secure) to just apply the solspace form classes to the regular log in form.


Plugin stops working when logged out I have a plugin that sets the user group based on whether a hidden checkbox has been ticked on the sign up form.

The plugin works exactly as I want it to while I'm logged in, but as soon as I log out the form reverts to default behaviour.

I can't find anything in Google about plugins misbehaving when someone logs out. Does anyone know what's going on and how I can overcome it?

Plugin code below;

public function init() {

    craft()->on('users.saveUser', function(Event $event) {

      $user = $event->params['user']

      if ($event->params['isNewUser']) {

        $groupPreference = $user->getContent()->groupPreference;

        if (in_array("trade", $groupPreference)) {

           craft()->userGroups->assignUserToGroups($user->id, 3);

        }

      }

    });

}

When I'm logged into the backend using my admin account and I use the form to sign up a new fake user, it works as desired and assigns the new user to the 'trade' group. If I'm logged out it just assigns the user to the default 'customers' group rather than 'trade'.

When you're logged in as an admin and test this for a new fake user, you have all of the necessary permission to perform the operation (including assigning new user/group permissions).

When you're not logged in as any user, you're missing the necessary "Assign user to groups" permissions a logged in user would need.  New users are going into the "customers" group, because presumably in Settings->Users->Settings in the Control Panel, you've got front-end registration enabled and you've assigned the default group to be "customers".

Having said that, here's a Craft 2 plugin that probably does what you're looking for. https://github.com/lindseydiloreto/craft-autoassignusergroup


How can I search for entries that are enabled OR disabled? Within a plugin I am fetching existing entries using the CriteriaModel class as documented here http://buildwithcraft.com/docs/plugins/working-with-elements#fetching-elements, specifically like this:

$existing = craft()->elements->getCriteria($this->entry->elementType)->first(array(
    'someHandle' => 'someValue'
))

However I am finding this only returns a result if an ENABLED entry is found. I can see that I can search for ONE particular enabled state as follows:

$existing = craft()->elements->getCriteria($this->entry->elementType)->first(array(
    'someHandle' => 'someValue',
    'enabled' => 1
))

Or...

$existing = craft()->elements->getCriteria($this->entry->elementType)->first(array(
    'someHandle' => 'someValue',
    'enabled' => 0
))

But how can I search for ALL entries regardless of the enabled state?

And also, what is the difference between the status and enabled properties on the model? I can see constants for ENABLED, DISABLED and ARCHIVED. I'm not clear on how this differs from the boolean value that the enabled property has.

I haven't tried this in php, but on the 'template' side there is an attribute called 'status' which you might try. I assume it would work in php as well.

$existing = craft()->elements->getCriteria($this->entry->elementType)->first(array(
    'someHandle' => 'someValue',
    'status' => null
));

Default is 'live'; other values would be 'live', 'pending', 'expired', 'disabled', and null. Here's the docs for craft.entries.status. Let us know if it works.


Overwriting specific method in plugin I want to expand functionality of perform plugin with generating pdf from message submission data and attaching it to email this plugin sends.

I can't use events for this, because this plugin doesnt emit any. Can i somehow overwrite specific method in craft cms plugin, without resorting do directly changing code in vendor directory?

If the methods you need to alter are part of an auto-instantiated Service in the PerForm plugin, you might consider using Yii 2 “Behaviors.”

From the docs:

  …to attach a behavior dynamically, call the yii\base\Component::attachBehavior() method of the component to which the behavior is being attached…

  Source

So, in a custom Craft module, you might put something like this, in your init method:

use perfectus\perform\PerForm;
use modules\mymodule\MyBehavior;

// ...

PerForm::$plugin->emailService->attachBehavior('myBehaviorHandle', new MyBehavior);

This gives you a chance to monkey-patch the service with your own functionality… but I can't speak to how inheritance works, or whether you'll be able to call parent::myPatchedMethod($args) (or, in Behavior-land, $this->owner->myPatchedMethod($args)) to ensure the least code is duplicated.

Overall, I agree with Indigo: The best way to ensure this will continue to work is to make a PR to the plugin that adds support for events at key moments, and shuttles the right kind of data around to accomplish what you want. This is the only way to ensure you have a stable event API.


How to get the Twig Text extension loaded I'd like to add the Text extension:

http://twig.sensiolabs.org/doc/extensions/index.html#extensions-install

Which seems very useful because of the truncate functionality. Any idea on how to accomplish this?

(this could've been installed by default)

Check out the Craft Plugin documentation on adding a Twig extension with a plugin. There is no clean way to add extensions manually without a plugin, as the changes might be overridden with Craft updates.


Multiple relatedTo conditions using a combination of "and" and "or" We're trying to make a filter that allows you to pick multiple items from 1 category, and multiple items from another category and return back all appropriate elements.
We're in PHP land not twig so the starting point we have is...

$results = Entry::find()
    ->type('recipe')
    ->relatedTo($conditions)
    ->all();

The pseudo query would be...
SELECT * FROM `entries`
WHERE
 (`food_type` = "cake" or `category` = "burger")
AND
(`weather` = "summer" or `tag` is "hot")

I've got the IDs and the hydrated models/elements of each category but can't figure out how to nest the conditions using the relatedTo method on the query..
Thanks

It seems that the relatedTo is by default an or, so you only need to define and once when the rest will be considered or e.g.
$query = Entry::find();

// Convert these IDs into Entries/Category models first.
$foodTypes = [1, 3, 5];
$weathers = [7, 4];

$query->relateTo([
    'and',
    ['targetElement' => $foodTypes],
    ['targetElement' => $weathers],
]);

return $query->all();

This will make sure each array passed into relateTo is considered an and group but the items within that are considered as an or group.


First and Last day of Week + Month in Twig If i provide the week#, how might i go about getting the first day (and month) and the last day (and month) of that particular week?

This week for instance would be April 26 and May 2

I know in PHP i can do the first and last day of the week like so:

$day = date('w');
$week_start = date('m-d-Y', strtotime('-'.$day.' days'));
$week_end = date('m-d-Y', strtotime('+'.(6-$day).' days'));

But i'm not sure how to translate that to twig and of course also include the month.

That code in Twig would be:

{% set day = now|date('w') %}
{% set weekStart = now|date_modify("-#{day} days")|date('m-d-Y') %}
{% set weekEnd = now|date_modify("+#{6-day} days")|date('m-d-Y') %}


Managing a large number of Variants in Craft Commerce I'm currently building a site for a client who's products vary in price depending on the width / height selected. Essentially what this means is each product has around 70 possible variations, each with it's own price.

My initial idea was to inject some JS that would allow the client to manage the variants in a table that would automatically generate / update the variants based on the contents of the table. Unfortunately, as far as I can tell, there is no way to access the JS that manages the variants as it's all done in a self contained, anonymous class.

I also tried creating a custom Purchasable entry type that would let me dynamically set the price of the of the line item based off the selected width & height. The keyword there being tried. I'm still trying to get to grips with custom Entry Types, and trying to get it to work with Commerce on top of trying to get it to work at all has made me, well, somewhat less than successful.

Has anyone had any success with managing large numbers of variants, or does anyone know of a simpler way to achieve what I'm after?

I'll go ahead and add this as an answer with a bit more detial....we have a large number of variants in total - about 50 different box sizes for about 110 types of product (each product has ~ 10 sizes associated with it).  In addition, we do services and there are about 50 variants there, for each of about 12 products.

In all, the simplest solution if things are relatively static is a bit of data entry...people, in my experience, worry far too much about programmatically generating things that then become hard to maintain (ecommerce tends to have al ot of exceptions and unusual scenarios and programmatic things soon get out of hand) - sometimes a tedious hour or two of data entry is actually a much more effective long term solution to the problem.  (And they invented student/interns for this right?!).

That said, Craft's excellent relations system can help a lot here - if your variation sizes are standard things, you can create a section to store your 'standard boxes' or 'standard variants' or whatever, and then relate these to your variants using an entries field on your variants for that product type.

Then, in your templates and/or shipping plugin etc, you simply refer to these standardised entries - rather than the variant itself - to get the data you need for your width, height, depth, and weight.  This can dramatically reduce your data entry work and keep things MUCH more DRY - there's one standardised place to add/change/remove data for your variants.  It's very effective...but it does mean you do need to have your own shipping plugin as you're sort of over-ruling Commerce's default behaviour here.

(One great thing Commerce could do to help and avoid the need for a plugin here would be to make it an option to specify a bit of twig for these standard fields so you could do things like specify a default value for height of  {standardBox.first().height} -  where standardBox is a field on the variant and that would then be parsed into the product when it is saved...)


Craft CMS GraphQL count query I've got the GraphQL code posted below, but I'm not sure how do I count the total of returned products .
Do I need another query just for the products without offset ? I need it for a pagination functionality
query Products($offset: Int, $priceBetween: [QueryArgument]) {
  products(limit: 9999, orderBy: "dateCreated DESC", offset: $offset, defaultPrice: $priceBetween) {
    id
    defaultPrice
    title
    ... on furniture_Product {
      productThumbnail {
        url @transform(width: 300, immediately: true)
      }
    }
  }
}

Try using _count -- there are some examples here: https://github.com/craftcms/cms/issues/4847


Is there a JS event triggered when a new widget is created? Pretty straightforward problem...

On the dashboard, I click "New Widget".
I select "My Custom Widget" type.
A new instance of "My Custom Widget" appears on the dashboard, ready to be edited.

How can my widget be self-aware that it has just been created?

I need the widget to perform some very minor JS when it initially loads. Is there an existing JS event which would be triggered in this scenario?

It appears when a new widget is created it has a variety of classes (such as new and loading-new) that don't exist on established widgets:

class="widget new loading-new myplugin_mywidget flipped last"

It's also possible to add javascript to the widget settings file that gets rendered for your widgets settings. In the admittedly lame (but illustrative) example below, your new widget will get the text color of red, and after it is saved and the page reloads, no red color will be applied.

{% includejs %}
(function(){
    $('.widget.new.myplugin_mywidget').css('color', 'red');
})();
{% endincludejs %}


Infinite scrolling with Craft? I'm looking to create an infinite scrolling section of entries on a site we're building. Has anyone tackled this yet? What's the best way to approach this?

Here's the approach that work for me. Using Infinite Scroll jQuery plugin.

In the header, I'm checking whether this is AJAX request or not and use different layout based on that. This is optional though.

{% if craft.request.isAjax %}
{% set layout = "_ajaxLayout" %}
  {% else %}
{% set layout = "_layout" %}
  {% endif %}

{% extends layout %}

In the content area, I have:

{% paginate craft.entries.section('news').limit(3) as entriesOnPage %}
    {% for entry in entriesOnPage %}

{{ entry.title }}

{{ entry.postDate|date("M d, Y") }}

                {{ entry.body }}

    {% endfor %}

    {% if paginate.nextUrl %}

        Next Page

    {% endif %}

{% endpaginate %}

Then, somewhere in the footer (note the If, I put it to make sure the infinite scroll fors only on first page)

{% if craft.request.pageNum==1 %}

{% paginate craft.entries.section('news').limit(3) as entriesOnPage %}
{% if paginate.nextUrl %}

{% endif %}
{% endpaginate %}

{% endif %}


How to include a lightswitch for each related entry in the source element of a relationship I have a Services section in which I keep a related entry field for News. (News by Service) The News items to be displayed for each service are selected in a "News" entries field in the Service entry. For each related news entry, I need to be able to include Lightswitch booleans for "alert" and "pinned", each with different behaviors on the front end. For instance, when an admin adds a related news entry to a service, they also should be able to determine if that new entry is either an alert or a pinned news item, but only for the current service.

I'm able to included related news in each service template, but I'm unsure how to accomplish having a lightswitch that appears for each related news item in the services cp. So that, for instance, news entry A is only an alert in Service B. Or news entry C is only pinned for Service D.

I guess I could create pinnedInService and alertInService entry fields in the News section, but this seems convoluted. Maybe this is best done in the News item, rather than in the Services entry? I'd also like to be able to expire or unpin the news entries based on a date field (also per service).

Any direction on how to accomplish this? Thanks in advance!

You are correct, you would not want to add those fields to the news items directly. Like you said, it would cause problems if you wanted a News item pinned on one service but not pinned on another one.

The best solution here (imo) is to utilize a Matrix field (or possibly a Table or SuperTable field, depends on your preference). So I would create a Matrix field for your service entries called News Items or whatever. Than each news item block would have several fields:

the actual related entry field where you would pull in the news entry
a lightswitch field for pinned
a lightswitch field for alert
a date field you could use to expire the news block
etc...

This would enable you to set these settings on each news block on the individual service entries, so you're not muddying up the news items themselves or contaminating other service pages where you may want a news item "pinned" or "alerted". And again, you could also use a SuperTable or maybe even a Table field instead of Matrix - just depends on what you prefer.


How to link to a page, but only if the page status is active This is probably a really basic question, but I can't figure out how to check the status of a page before I link to it.

I have a link in my footer to 'Policy' page. But if the page status is inactive, I don't want that link to show. How can I perform this simple check?

Thanks,

Mark

This should work.

{% set policy = craft.entries.section('policy').first() %}
{% if policy %}{{ policy.title }}{% endif %}

ElementCriteriaModel should only return active records by default.


Plugin in subfolder for github? Is it possible to have Craft plugins in subfolders of craft/plugin/ instead of having them right in that folder?

So that I can have a parent directory that is my git repository craft/plugin/mypluginrepo/ containing a README.md and other files and folders besides the actual plugin craft/plugin/mypluginrepo/myplugin/.

I know you can change the plugins path via the PHP Constant:
define('CRAFT_PLUGINS_PATH', '../craft/plugins/subfolder/');

unfortunately this only allows me to set one folder.

I don't think it's currently possible.  There are several places where we're explicitly checking for the plugin's handle as a folder directly underneath whatever craft()->path->getPluginsPath() is returning.


Best way to bulk email an attachment? I need to take a file, and email it to a large group of people. Naturally, I'll be using a custom plugin Controller to trigger the email blast.

I'm already aware of this similar thread, but I don't believe it will solve my problem. If I remember correctly, Craft's native email model isn't capable of sending to more than one person at a time. More importantly, I don't want our server to be labeled as a spammer!

Would it make sense to run this process through a Task? Each individual email could be sent out as a separate step in the task.

What is the best way to bulk email an attachment?

There's nothing that says you have to go through Craft's EmailModel/EmailService for this.

Craft ultimately uses the PHPMailer library, so you can instantiate it directly and use whatever settings you need (or use a completely different library).

I assume you don't want to cram everyone into to "To Address", so is the plan to set the "To Address" to yourself and BCC the recipient list?

Depending on the number of emails you need to send, I'd probably just have your plugin read from the file and insert into a database table.  Then you could setup a cron job to hit your plugin's controller action to send out (one at a time) X emails over Y time period and delete those from the table until its empty.

As far as not getting flagged as a SMTP relay, in addition to throttling email rates, there are definitely other things you can do to reduce your chances.


Define POST or GET for a route Is there a way to define a route that can only receive POST data?
In Laravel you can do this:

Route::post('admin/content/{id}', 'ContentController@update');

Is there a way to do this with a Craft route?

Tried this to no avail:

'POST, newseventsapi/v1/login' => array('action' => 'api/Login')

Taking out the comma after POST seems to work

Correct.  A common is only needed if you want to allow multiple HTTP methods like POST,PUT.

Here's the Yii documentation on the topic: https://www.yiiframework.com/doc/guide/2.0/en/runtime-routing#http-methods


Including block templates under different subdirectories How do I include block types that don't all sit under the one directory? My folder structure:

 - images
  - _blockName.html
 - mockups
  - ...
 - text
 - special

How I'm currently including the blocks (which isn't working):

{% extends "_layout" %}

{% block content %}
    {% for block in entry.widgets %}
        {% include "widgets/_" ~ block.type ignore missing %}
    {% endfor %}
{% endblock %}

How do I let craft know to look under each subdirectory?

It could get unwieldy if you have too many subfolder options, BUT... You CAN supply a list of templates to Twig's include tag. Twig checks each option, and includes the first template in the list that exists:

{% include
   [
    '_widgets/_images/_'  ~ block.type,
    '_widgets/_mockups/_' ~ block.type,
    '_widgets/_text/_'    ~ block.type,
    '_widgets/_special/_' ~ block.type
   ]
   ignore missing
%}

(The ignore missing tells Twig to fall back to rendering nothing if none of the templates exist. Otherwise it would throw an exception. A popular alternative is to have a default fallback template as the last item in the list.)

Bonus 2¢: I think it's good practice to keep include templates in hidden folders (i.e. _widgets/ instead of widgets/) — to signify to yourself and others that the directory does not match with a public route, and that its contents are never meant to be displayed directly.


Craft 3 Upddate: Plugin Errors I have tried to get a number of plugins from the Plugin Store but each time on install, I get the following errors:

Status: Not Found

Response: {"error":"Template not found: internal_error.html"}

Has anyone seen this as well?

internal_error.html isn't a file that is shipped with Craft.

Most likely what is happening is that you're running into some fatal PHP error (like bumping into your php.ini file's memory_limit or max_execution_time setting) and your host has configured all fatal errors (or anything with a 500 Internal Server Error response code) to redirect to their internal_error.html template.

Craft doesn't know how to route to that template, so you get the error above.

I'd check Craft's logs at craft/storage/logs and/or your web server's error logs for the real underlying error.


Maintaining order when getting by entries by ID I'd like to get a certain set of entries in a specific order, but the element query comes back ordered by the default 'postDate desc'

{% set ids = ['4213','3200','4204','4212']
 %}

{% set orderedEntries = craft.entries().id(ids).order('id').all() %}

{{ dump(orderedEntries.ids) }} <- not the same order as the array!

It feels like there should be a relatively simple way of doing this in craft/twig, am I missing something? Or should I just resort to SuperSort?

You can do this by adding .fixedOrder(true) to your query:

{% set ids = ['4213','3200','4204','4212'].fixedOrder(true) %}

https://docs.craftcms.com/v3/dev/element-queries/tag-queries.html#fixedorder


Create custom field type with dynamic data I would like to create a custom dropdown field with dynamic data

Ideally I would get data from one of my services, and then inject it dynamically in the HTML select field

I read the plugin documentation on custom field types, but couldn't find anything about this

You should have a look at the LJ Dynamic Fields plugin, it sounds like everything you’re after is already doable with this plugin and if not, you can study the code or build upon it.


Getting Stripe to work with Commerce We're using Stripe for an ecomm project that we're testing out right now and nothing is hitting Stripe. If we use a bad card number (per Stripe's docs) like 4000000000000002, the order still goes through.

The Stripe account is brand new (hasn't fully been activated yet) and in Test mode and the test secret and publishable keys are in Commerce's settings. I'm not sure what else to check.

EDIT:

I had forgotten stripe.js altogether but now I'm getting "Payment information submitted is invalid." which I think is a Craft/Commerce error. Here's a link to my checkout template code. The wrapper template (extended template) contains this javascript before the closing body tag.

Issue was not RTFM. :) Basically I didn't include every part of the stripe.js setup


Unable to upload PNG images I'm running Craft CMS on OS X Yosemite (Server.app) and cannot upload PNG images. JPG uploads are working as expected. I get a log message like the following:

2015/01/15 08:39:08 [error] [exception.Imagine\Exception\RuntimeException] exception 'Imagine\Exception\RuntimeException' with message 'Unable to open image .../craft/storage/runtime/temp/assets54b77cabe51c25.46473389.png' in .../craft/app/vendor/imagine/imagine/lib/Imagine/Gd/Imagine.php:96
Stack trace:
#0 /*/craft/app/etc/io/Image.php(136): Imagine\Gd\Imagine->open('...')
#1 /*/craft/app/services/ImagesService.php(84): Craft\Image->loadImage('...')
#2 /*/craft/app/services/ImagesService.php(153): Craft\ImagesService->loadImage('...')
#3 /*/craft/app/assetsourcetypes/BaseAssetSourceType.php(183): Craft\ImagesService->cleanImage('...')
#4 /*/craft/app/assetsourcetypes/BaseAssetSourceType.php(145): Craft\BaseAssetSourceType->insertFileByPath('...', Object(Craft\AssetFolderModel), 'HSS_Highlife_20...')
#5 /*/craft/app/services/AssetsService.php(673): Craft\BaseAssetSourceType->uploadFile(Object(Craft\AssetFolderModel))
#6 /*/craft/app/controllers/AssetsController.php(71): Craft\AssetsService->uploadFile('1', NULL, 0, NULL)
#7 /*/craft/app/framework/web/actions/CInlineAction.php(49): Craft\AssetsController->actionUploadFile()
#8 /*/craft/app/framework/web/CController.php(308): CInlineAction->runWithParams(Array)
#9 /*/craft/app/framework/web/CController.php(286): CController->runAction(Object(CInlineAction))
#10 /*/craft/app/framework/web/CController.php(265): CController->runActionWithFilters(Object(CInlineAction), Array)
#11 /*/craft/app/framework/web/CWebApplication.php(282): CController->run('uploadFile')
#12 /*/craft/app/etc/web/WebApp.php(754): CWebApplication->runController('assets/uploadFi...')
#13 /*/craft/app/etc/web/WebApp.php(261): Craft\WebApp->_processActionRequest()
#14 /*/craft/app/framework/base/CApplication.php(180): Craft\WebApp->processRequest()
#15 /*/craft/app/index.php(62): CApplication->run()
#16 /*/public/index.php(14): require_once('...')
#17 {main}
REQUEST_URI=/index.php?p=admin/actions/assets/uploadFile
HTTP_REFERER=http://*/index.php?p=admin/entries/banners/5-highlife-vanguard
---
2015/01/15 08:39:08 [error] [application] Unable to open image craft/storage/runtime/temp/assets54b77cabe51c25.46473389.png

It looks like a problem with the Imagine library not being able to open the uploaded PNGs?

Is there anything special about that PNG file?  It's likely that it's in a PNG format that GD does not support.

Install Imagick and try again.  It handles a much wider range of formats, is generally less buggy and produces better results.  Craft will automatically use it if it detects that it is installed and available to PHP.


How to use a note from the Line Item Model Working with the example Commerce templates. In the cart template there is an example for adding a note. https://craftcommerce.com/docs/line-item-model#note

The code for this form:

<form class="shopForm" method="POST">
<input type="hidden" name="action" value="commerce/cart/updateLineItem">
<input type="hidden" name="redirect" value="shop/cart">
<input type="hidden" name="lineItemId" value="{{ item.id }}">
{{ getCsrfInput() }}

    Note
    <input type="text" size="20" name="note" value="{{ item.note }}">

    Quantity
    <input type="number" name="qty" min="1" value="{{ item.qty }}">

<input type="submit" class="btn btn-outline" value="Update">

Very useful but after submitting the form, how can we display this later on in the ordering process? For example on a receipt or the order overview. Also can we view this in the Commerce back end? I was not able to find …

Can anybody shed some light? Thanks!

The example template show how to display the note, but here is the jist of it:

{% for item in cart.lineItems %}
 {{item.qty }} x {{ item.description }} - {{ item.note }}
{% endfor %}


Page is Not listed in Backend One of the pages in the menu header is called Order Online, which takes users to a separate website.  I want to change the link where it takes users to but when I went to the backend of the site, the page is not listed under pages, nor is it listed under entries.  I have no idea where it is listed!

Since you said this “page” is merely a link to an external site, you’re not going to see it in the Entries section of the Control Panel. Most likely this page/link is being setup either in some menu plugin (e.g. A&M Nav) or in your Twig templates (in your master/layout template or some included template specific to the menu or nav).


Displaying how long til post expires I'm trying to display how long til a certain post expires depending on a date/time field.

Example

  Expires in 13 days.

My field is currently displayed by doing {{ entry.expiration }}

I just don't know how I would just display the days remaining until this date.

Thanks

Your entry.expiration is actually an object of type DateTime thus you'll have the full power of PHPs DateDiff functionality

$interval = $datetime1->diff($datetime2);

In Twig this is something like

{% set difference = now.diff(entry.expiration) %}
{{ difference.format('%R%a days') }}

now should be the current date


How do you iterate over Matrix field in a Craft 3 plugin? $entry = Entry::find()->section('my_section')->relatedTo($entry)->all();
$entry['myMatrixField']; // What do I do with this??

I know there are tutorials about how to handle Matrix fields in plugins in Craft 2, but how do I do this in Craft 3?

If you had a Matrix field with a handle of matrix and it had a Matrix Block Type with a handle of MyMatrixBlock and it had a Plain Text field with a handle of text, this is how you'd grab it in PHP.

$entry = Craft::$app->getEntries()->getEntryById(2);

foreach ($entry->matrix as $matrixBlock) {
    if ($matrixBlock->getType()->name === 'MyMatrixBlock') {
        // Grab a text field from the block.
        $textField = $matrixBlock->text;
    }
}


Disable "dynamic links" in rich text fields When we're adding a "link > link to an entry" to a rich text field, this will result in a link to https://www.site.com/page#entry:3962:url and we understand what the purpose is of this additional #entry:3962:url, but is there a way to disable this?

The multi-domain setup we created is not compatible with this feature, so it will create links that are broken. The easiest fix for our customer is to disable this feature all together. Is that possible and how?

and we understand what the purpose is of this additional #entry:3962:url, but is there a way to disable this?

Currently not.  You'd need to write a Craft/Redactor plugin that used the addRichTextLinkOptions hook to do something similar to what the default "Link to an Entry" does, but with your own custom logic.


Passing data back to form on invalid submission I currently have a form that is being displayed to the user via a custom route.

The form submits to a controller. The first thing the controller does is populate a custom model and validates it.

If the model fails validation, I want to skip the rest of the controller and pass the model back to the form. What is the best way to do this? I tried using craft()->urlManager->setRouteVariables and a $this->redirect, but the route variable didn't seem to come through, which I imagine is because setRouteVariables isn't supposed to be used like that.

You can call setRouteVariables and not return anything from your controller so the request continues as normal.  Craft does this all the time with it's own controllers.  See this answer for the general controller workflow.


Redactor stripping script/html tags I wasn't to allow a user to enter html into the Rich Text field.

The html in question is:

I can save the entry and on the front end the content displays ok - but when I go back in to edit the entry it is no longer there - the div and script tags have been removed.

I tried adding this

replaceDivs: false,

to the config but it doesn't make any difference

Please do yourself a favor and don't do this  in Redactor. Find a solution with Matrix (and/or Super Table) to add things like this in-between your text blocks.


Pull first image from rich text field Is there a way to output the first image of a rich text field?

At the moment the template code is as simple as:

{{ entry.body }}

The purpose is so that I can use the image in the meta section of the template. If there is no easy solution I could change it to be a Matrix field.

I think the best way to do this, is by creating a small Twig extension plugin that uses PHP's html parser to find the first occurrence of an IMG tag and return the src of that tag to your template. This is a step-by-step explanation of how to create your very own Twig filter.

You could then to this:

{{ entry.body | firstImageSrc }}

And it would return the url you need.

The easiest way, however, is to add an asset field to your Entry Type's field layout and choose a file manually.


MySQL CPU pegged on specific query Very similar (almost exact) to this question: Poor performance on midsized site / Queries without index?

CPU keeps getting pegged to 100% for MySQL, which makes the admin interface very slow (the site is cached using fastCGI, so generally the site still performs well regardless).

The troublesome query:

FROM (SELECT `elements`.`id` AS `elementsId`, `entries`.`sectionId`, `entries`.`typeId`, `entries`.`authorId`, `entries`.`postDate`, `entries`.`expiryDate`
FROM `elements` `elements`
JOIN `elements_i18n` `elements_i18n` ON elements_i18n.elementId = elements.id
JOIN `content` `content` ON content.elementId = elements.id
LEFT JOIN `relations` `sources1` ON (sources1.targetId = elements.id)
LEFT JOIN `relations` `targets1` ON (targets1.sourceId = elements.id)
JOIN `entries` `entries` ON entries.id = elements.id
JOIN `sections` `sections` ON sections.id = entries.sectionId
LEFT JOIN `structures` `structures` ON structures.id = sections.structureId
LEFT JOIN `structureelements` `structureelements` ON (structureelements.structureId = structures.id) AND (structureelements.elementId = entries.id)
WHERE (((((elements_i18n.locale = 'en_us') AND (content.locale = 'en_us')) AND (elements.archived = 0)) AND ((elements.enabled = 1) AND (elements_i18n.enabled = 1) AND (entries.postDate <= '2017-12-29 15:41:28') AND ((entries.expiryDate is null) OR (entries.expiryDate > '2017-12-29 15:41:28')))) AND (elements_i18n.enabled = 1)) AND ((sources1.sourceId='52') OR (targets1.targetId='52'))
GROUP BY `elements`.`id`) derivedElementsTable

What are CPU has looked like:

I'm not sure where I should start hunting this down. This appears to only happen for the en_us locale, I haven't recorded another locale showing this. This is on a staging site on Digital Ocean, so it's getting zero traffic. It's also being managed by Forge on PHP 7.1.

Could I get any advice for hunting down the php that might be leading to this? It's not happening as a result of any clear action.

I wouldn't be too worried about MySQL using 100% CPU, especially on a multi-core VPS. But a good way to track down things like this is to enable the MySQL slow query log

You can set whatever thresholds you want, and then peruse the log at your convenience to see the queries that are actually slowing things down.