Add Adjuster after Order is completed? I need to add an adjuster after the order is completed, but can't get it working.

The reason is that the customer can order a individual picture, after that he get's a preview of the picture where he can proof the image and only when he confirms the preview he has to make the payment. In case of payment by bill, there is a payment fee about 5 EUR.

The adjuster I made works, but only if the order is not completed. Is there any way to implement this?

Or can i add a payment fee via a custom payment gateway, that adds to the bill at the end?

At the moment, both are not possible. The order is locked from recalculation when the order is marked as completed - the final price being locked in.

In a future release we will introduce the concept of order editing after order completion.

Right now, you could manually insert an adjustment row into the database, along with the changes to the order's order.baseShippingCost but you would need to make sure the order.totalPrice and other calculated fields would also be updated in the database to make the order internally consistent.


Delete a relation in frontend form We have a change profile page where members can choose out of the users table who of the other members is their mother (or father).

Below my (simplified) user profile form

<form method="post" accept-charset="UTF-8" enctype="multipart/form-data">
<script>$(':checkbox').checkboxpicker();</script>
{{ getCsrfInput() }}
<input type="hidden" name="action" value="users/saveUser">
<input type="hidden" name="redirect" value="leden/wijzig-profiel?m=updated">
<input type="hidden" name="userId" value="{{ currentUser.id }}">
<input type="hidden" name="fields[mother][]" value="">

<label for="mother">{{ 'mother'|t }}</label>
<select name="fields[mother][]" >
    <option value="">There is no mother</option>
    {% for mother in mothers %}
    <option value="{{ mother.id }}">{{ mother.name }}</option>
    {% endfor %}
    {% for user in users %}
    <option value="{{ user.id }}">{{ user.name}}</option>
    {% endfor %}
</select>
<input type="submit" value="{{ 'Save'|t }}" name="proceed" >

I've tried to empty the field mother but that results in a CDbException error.

CDbCommand faalde tijdens het uitvoeren van volgend SQL statement: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`familywebsite`.`craft_relations`, CONSTRAINT `craft_relations_targetId_fk` FOREIGN KEY (`targetId`) REFERENCES `craft_elements` (`id`) ON DELETE CASCADE). The SQL statement executed was: INSERT INTO `craft_relations` (`fieldId`, `sourceId`, `sourceLocale`, `targetId`, `sortOrder`, `dateCreated`, `dateUpdated`, `uid`) VALUES (:row0_col0, :row0_col1, NULL, :row0_col3, :row0_col4, :row0_col5, :row0_col6, :row0_col7), (:row1_col0, :row1_col1, NULL, :row1_col3, :row1_col4, :row1_col5, :row1_col6, :row1_col7). Bound with :row0_col0='136', :row0_col1='1', :row0_col3='', :row0_col4=1, :row0_col5='2016-10-08 09:54:35', :row0_col6='2016-10-08 09:54:35', :row0_col7='e4211e99-5bbd-46c1-b703-c44e82bc4667', :row1_col0='136', :row1_col1='1', :row1_col3='2409', :row1_col4=2, :row1_col5='2016-10-08 09:54:35', :row1_col6='2016-10-08 09:54:35', :row1_col7='c0fb9927-89f1-4993-ba26-bc47a63bdc50'

This I can understand because the mother is a relation of the user, and by clearing the mother field value, it probably does not delete the relation and it will give and error like it does.

So question is how to delete the relation with mother field?

I believe you're getting that error because you're supplying an array ([]) for the mother field and the only value in that array would be an empty string ("") if they select the There is no mother option. So what Craft is attempting to save as a relation is [""]. Instead of an array of integer ID numbers, it's getting an empty string which isn't a valid value.

Even if you remove the value attribute of the option tag for the There is no mother option, the field will use the inner text of the tag as the value, so this does not solve your problem either.

One suggestion would be to use radio buttons instead and do the following:

<input type="radio" name="" value=""> There is no mother
{% for mother in mothers %}
    <input type="radio" name="fields[mother][]" value="{{ mother.id }}"> {{ mother.name }}
{% endfor %}
{% for user in users %}
    <input type="radio" name="fields[mother][]" value="{{ user.id }}"> {{ user.name }}
{% endfor %}

This will keep the field empty if someone selects the There is no mother option.


Search entries ordered by sections Is it possible to perform a search and have the results grouped/prioritized by sections?

e.g. something like:

craft.entries.section(['sec3', 'sec5', 'sec1']).search(...).limit(6) as page_info, page_entries

I want sec3 entries first, followed by sec5 and sec1 entries.

Note that I want to use the built-in pagination mechanism and would not like to use hacks such as searching tons of entries and manually group the results by sections.

Something like this should get you started, q is the querystring in your results url:

{% set query = craft.request.getParam('q') %}
{% set entries = craft.entries.search(query).level(1).order('score') %}
{% set grouped = entries|group('section') %}

Results for &ldquo;{{ query }}&rdquo;

        {% if entries|length %}
        {% for section, entriesInGroup in grouped %}

{{ section }}

            {% for entry in entriesInGroup %}

{{ entry.title }}

            {% endfor %}

        {% endfor %}
{% endif %}

Not sure how pagination fits in here but I'm sure others will chime in.


Get Entry Edit Link in Twig I want to add an "Edit entry" button on each page for admin users. Am I overlooking a simple way to output the Edit link to the CP edit page for the current entry? Curious if there is something like {{ entry.editLink }}

There is! It's called cpEditUrl.

{% if currentUser %}
   {% if currentUser.isInGroup('admin') %}
       Edit entry
   {% endif %}
{% endif %}

Or shorter (thanks to MISC):

{% if currentUser.admin %}
    Edit entry
{% endif %}

Or forget user group altogether (thanks to Phil Gyford and bennobo):

{% if entry.isEditable() %}
    Edit entry
{% endif %}


Category not loading template I have created a new Category on a Craft 3 website but it will not load the template specified. Have other categories all working fine and can't get this one working at all.

Category Config below

I expect this to load my template /pupil-of-the-month/index.html

As per the below image in my templates folder.

But when I click on the category url - http://local.domain.com/pupil-of-the-month/class/p1

I get a not found error -

Template not found: pupil-of-the-month/class

Why is this Category not following the template specified in the admin settings?

The template path specified in the admin should point to a single file, not a directory.

index files are only loaded when the Craft router falls all the way through element URIs and starts to look in your templates folder—in your case, that would be local.domain.com/pupil-of-the-month.

I suspect the confusion lies in that the router does eagerly look inside a directory for index.* templates in some narrow cases (as stated above), but that the pattern is not adopted by Category/Section/Tag settings.

See the official Routing Docs for more information about the process Craft uses to resolve the template for a request.


Filtering entries based on category? I want to filter data based on category, I would prefer to do this using a join statement, but I can't figure out how an entry is related to its category. I had the same problem with matrix field, but figured it out after hours of research, the code for this is below. A similar statement to filter based on category would be great.

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'affiliates';
$criteria->limit = null;
$query = craft()->elements->buildElementsQuery($criteria);
$query->join('matrixblocks matrixblocks', 'matrixblocks.ownerId = entries.id');
$mat_name = 'field_handle';
$query->join('matrixcontent_'.$mat_name.' matrixcontent_'.$mat_name, 'matrixcontent_'.$mat_name.'.elementId = matrixblocks.id');
$query->join('relations relations', 'relations.sourceId = matrixcontent_'.$mat_name.'.elementId');
$query->join('content '.$mat_name, $mat_name.'.elementId = relations.targetId');
$query->andWhere($mat_name.".title"." IN ('abc', 'def')");

Craft has a pretty solid engine for relational queries, so unless what you want to do is totally outside the box, there's a good chance you can accomplish what you want by using the relatedTo parameter available to the ElementCriteriaModel. Note that the relatedTo entry in the docs pertain to templates and not plugin development per se, but aside from the syntax the concept and approach will be identical in PHP.

Here are some examples, since its not obvious to me exactly what you hope to achieve:

To pull entries related to a certain category:

$criteria = craft()->elements->getCriteria(ElementType::Entry, [
    'section' => 'affiliates',
    'limit' => null,
    'relatedTo' => [
        'element' => $category, // Instance of CategoryModel, or a category ID
    ],
]);

To pull entries related to multiple categories:

...
'relatedTo' => [
    'element' => $categories, // Array of CategoryModels or category IDs
],
...

To pull entries related to a category, where the relation is made in a certain Categories field:

...
'relatedTo' => [
    'element' => $category,
    'field' => 'someCategoriesFieldHandle',
],
...

To pull entries related to a category, where the relation is made in a certain Categories field on the EntryModel:

...
'relatedTo' => [
    'targetElement' => $category,
    'field' => 'someCategoriesField',
],
...

To pull entries related to a category, where the relation is made in a certain Entries field on the CategoryModel:

...
'relatedTo' => [
    'sourceElement' => $category,
    'field' => 'someEntriesField',
],
...

To pull entries with multiple possible relations, where any of the relational parameters can be met:

...
'relatedTo' => ['or', [
    'targetElement' => $categories,
    'field' => 'someCategoriesField',
], [
    'targetElement' => $someOtherCategories,
    'field' => 'someOtherCategoriesField',
]],
...

To pull entries with multiple possible relations, where all of the relational parameters must be met:

...
'relatedTo' => ['and', [
    'targetElement' => $categories,
    'field' => 'someCategoriesField',
], [
    'targetElement' => $someOtherCategories,
    'field' => 'someOtherCategoriesField',
]],
...

If you edit your question to include exactly what you want to do, I might be able to give you more specific advice or examples.


Required Fields for User Signup We have a user signup form (see http://thinkdif.co/me/signup) that has some extra required fields. When a craft field us missed out, the error code below works, however when a custom User field is not completed, the page does not save, but no error is presented.

We require errors on custom user signup fields, and also on the 'Update your profile' page that is presented later in the workflow.

Thanks for any help or examples. End goal is to have good required fields throughout the user workflow.

Dan

Example error code:

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

Edit:

Here is a gist of the full page. https://gist.github.com/slipstreamstudio/d8dd801d722c3f275b74

There was a bug in Craft such that when saving a user, if the username / email / password failed validation first, content validation would never get a chance to run.

Have just fixed that locally and it will go out in the next release.
The way you have your dropdowns defined (userCountry and occupation), they'll never fail validation because there will always be a value selected and submitted in $_POST.
The first name and last name fields on a user account are somewhat “special” fields.  There is currently no way to set them as required.  We've got some plans to revamp how user names are handled on “The List”™ for a future update.  In the meantime, if you want to make them required fields, you can create actual custom fields for them.


Update a user image on the front end using Vue.js and Ajax Following on from this question I am now looking at adding, deleting and updating a user's image on the front end using Vue.js and vue-resource. I have the delete functionality working no problem but I am having an issue with how I add and upddate a users' image.

Here is my test form code:

<form method="post" action="" enctype="multipart/form-data" accept-charset="UTF-8" @submit.prevent="submitForm">
  {{ getCsrfInput() }}
  <input type="hidden" name="action" value="users/saveUser">
  <input type="hidden" name="redirect" value="/">
  <input type="hidden" name="userId" value="{{ currentUser.id }}">

      Member Image
      <input id="avatar" type="file" name="userPhoto">

  <button type="submit" class="button is-primary">Save Profile</button>
</form>

Looking at the Craft log when you submit the form without Ajax it works successfully and this is the log:

$_POST=array (
  'CRAFT_CSRF_TOKEN' => 'Vq_qS8xUX_Z0d09MHA_n3lFLCse3hLuc5Vx0sREE|b95a7c106acaa1e421d409d2eb708ac2beb18b96',
  'action' => 'users/saveUser',
  'redirect' => 'members/profile/gareth
',
  'userId' => '39',
)

$_FILES=array (
  'userPhoto' =>
  array (
    'name' => 'new-me.jpg',
    'type' => 'image/jpeg',
    'tmp_name' => '/Applications/MAMP/tmp/php/phpfDqUNQ',
    'error' => 0,
    'size' => 395885,
  ),
)

My main question is how do I submit to the $_FILES array using ajax? When I post my form using ajax I get the following Craft log:

$_POST=array (
  'userPhoto' =>
  array (
    'name' => 'me.jpg',
    'type' => 'image/jpeg',
    'tmp_name' => '/Applications/MAMP/tmp/php/phpLha7Uh',
    'error' => '0',
    'size' => '117463',
  ),
  'deleteUserPhoto' => '',
  'userId' => '39',
  'action' => 'users/saveUser',
  'CRAFT_CSRF_TOKEN' => 'Vq_qS8xUX_Z0d09MHA_n3lFLCse3hLuc5Vx0sREE|b95a7c106acaa1e421d409d2eb708ac2beb18b96',
)

Is the only way to handle file uploads on the front end to create your own controller and work things out through that or can I set something within my ajax post that will add to the $_FILES array?

Here is my Vue.js code for review:

Vue.http.options.emulateJSON = true;
Vue.http.options.emulateHTTP = true;

var app = new Vue({
  delimiters: ['@{', '}'],
  el: '#app',
  data: {
    user: {
      userPhoto: {
        'name': 'me.jpg',
        'type': 'image/jpeg',
        'tmp_name': '/Applications/MAMP/tmp/php/phpLha7Uh',
        'error': 0,
        'size': 117463
      },
      userId: '{{ currentUser.id }}',
      action: 'users/saveUser'
    },
  },
  methods: {
    submitForm: function() {

      var data = this.user;

      data[window.csrfTokenName] = window.csrfTokenValue; // Append CSRF Token

      this.$http.post('/', data)
        .then(function(response) {
          // success stuff here
        });
    }

  }
});

In the end I found a solution which doesn't require creating my own controller. I am not sure it is possible to post directly to the $_FILES array in Craft but by using the native FormData object in Javascript you can basically pass all the form fields in the correct format to the vue-resource post method. I found this article useful on my search for solving what I needed. In doing this it kind of bypasses the Vue data model which is not exactly what I was after but it works well and keeps things simple. One caveat is that support for the FileData object is only on modern browsers but you can polyfill for older browsers.

Here is my final test form code:

<form method="post" action="" enctype="multipart/form-data" accept-charset="UTF-8" @submit.prevent="submitForm" id="imageForm">
  {{ getCsrfInput() }}
  <input type="hidden" name="action" value="users/saveUser">
  <input type="hidden" name="redirect" value="members/profile/{% include '_includes/helpers/user_profile_link' %}">
  <input type="hidden" name="userId" value="{{ currentUser.id }}">

  {% if currentUser.photoUrl %}
    <transition name="fade">

    </transition>

    Delete

    <input type="hidden" name="deleteUserPhoto" id="deleteUserPhotoInput" value="" v-model="user.deleteUserPhoto">

      Member Image
      <input id="avatar" type="file" name="userPhoto">

  {% else %}

      Member Image
      <input id="avatar" type="file" name="userPhoto">

  {% endif %}

  <button type="submit" class="button is-primary">Save Profile</button>
</form>

Here is my final Vue.js code:

Vue.http.options.emulateJSON = true;
Vue.http.options.emulateHTTP = true;

var app = new Vue({
  delimiters: ['@{', '}'],
  el: '#app',
  data: {
    user: {
      deleteUserPhoto: '',
      userId: '{{ currentUser.id }}',
      action: 'users/saveUser'
    },
    showImage: true
  },
  methods: {
    submitForm: function() {
      var form = document.getElementById('imageForm');
      var formData = new FormData(form);

      this.$http.post('/', formData)
        .then(function(response) {
          //this.updated = true;
        });
    },
    deletePhoto: function () {
      this.user.deleteUserPhoto = 'noMorePhoto';

      var data = this.user;

      data[window.csrfTokenName] = window.csrfTokenValue; // Append CSRF Token

      this.$http.post('/', data)
        .then(function(response) {
          this.showImage = false;
        });
    }
  }
});


How do you page through entries in a structure? I have a structure like below and need previous / next links on an entry such that they go back and forth between E, F, G and H. They shouldn't step into D or I.

I've been trying this, but I can't get it not to step into D or I.

{%  set prev = entry.getPrev({section: 'mySection'}) %}

    {% if not prev %}
        {% set prev = craft.entries.section('mySection').last() %}
    {% endif %}

    {{ prev.title }}

    {% set next = entry.getNext({section: 'mySection'}) %}

    {% if not next %}
        {{ craft.entries.section('mySection').order('lft desc').first().title }}
    {% endif %}

    {{ next.title }}

A

B
C
D

E
F
G
H

I

J
K
L

M
N
O
P

Craft provides many helpful methods to traverse structure sections and your use case is no exception.

Instead of using .getPrev() or .getNext(), try .getPrevSibling() or .getNextSibling() (or their aliases .prevSibling and .nextSibling.)

You could create prev/next links with something like this:

{% set prev = entry.prevSibling %}
{% if prev %}
    {{ prev.title }}
{% endif %}

{% set next = entry.nextSibling %}
{% if next %}
    {{ next.title }}
{% endif %}


How can I add custom validation rules to my plugin settings? I have a plugin that needs to perform some custom validation on one of its settings. How would I go about doing that?

The gist is, you will need to give your plugin a dedicated Settings model class, where you will have complete control over its validation rules and errors.

Here’s how to set that up:

Create a new Model class whose defineAttributes() method is based on your plugin's current defineSettings() method.

class Foo_SettingsModel extends BaseModel
{
    protected function defineAttributes()
    {
        return array(
            'settingName' => AttributeType::String,
            // ...
        );
    }
}

Give your plugin a getSettingsModel() function (instead of defineSettings()), which will return a new instance of your settings model.

class FooPlugin extends BasePlugin
{
    // ...

    protected function getSettingsModel()
    {
        return new Foo_SettingsModel();
    }
}

To perform the actual validation, you have two options:

Create a custom validator class (see the ones in craft/app/validators/ for examples), and make your plugin’s rules() method include it:

class FooPlugin extends BasePlugin
{
    // ...

    public function rules()
    {
        $rules = parent::rules();
        $rules[] = array('settingName', 'Craft\Foo_CustomValidatorClassName');

        return $rules;
    }
}

Override your plugin’s validate() method and just perform the validation directly from there:

class FooPlugin extends BasePlugin
{
    // ...

    public function validate($attributes = null, $clearErrors = true)
    {
        $validates = parent::validate($attributes, $clearErrors);

        if ($attributes === null || in_array('settingName', $attributes))
        {
            // Perform custom validation here
            // ...

            if (!$settingNameValidates)
            {
                $this->addError('settingName', 'Error message');
                $validates = false;
            }
        }

        return $validates;
    }
}

Finally, the last thing you’ll need to ensure is that your plugin’s settings template is actually showing the error messages associated with this setting:

{{ forms.textField({
    ...
    errors: info.getErrors('settingName')
}) }}


Assets Transform returns "Image cannot be found." I have two assets sources, Slideshow and Products. I have six Image Transforms.

On the home page I'm using a structure channel to play a simple slideshow and I'm using 3 transforms and all is working fine.

This code works fine:

{{ entry.productPhotos.first().geturl() }}

But this code throws an error:

{{ entry.productPhotos.first().geturl('productSlide') }}

If you go on my assets source path, the file is uploaded but the transform folder doesn't exist.

I tried clearing cache, deleting records in craft_assettransformindex, and most of the things suggested here, but with no luck. The weird thing is that the other Structure with the assets Slideshow works fine so it couldn't be something with the paths.

I'm using 'generateTransformsBeforePageLoad' => true, in my config/general.php file.

You can see on my phpMyAdmin screenshot that the filename is NULL in the table craft_assettransformindex but all the other transforms for the slideshow are there:

A long shot, but if it is indeed a path problem, this has seemed to help me keep my path(s) straight. I my config.php file, I'll set a parameter for environmentVariables like this:

...

'.dev' => array(
    'devMode' => true,
    'siteUrl' => 'http://mysite.dev/',
    'environmentVariables' => array(
        'basePath' => $_SERVER['DOCUMENT_ROOT'] . '/',
        'baseUrl' => 'http://mysite.dev/',
    )
)

...

Then when you are defining your asset sources, you can use this for "File System Path":

{basePath}assets/photos/products/

Then for URL try this:

/assets/photos/products


User Account Form Dropdown I have a Countries dropdown menu for signing up that i didn't have before. It used to just be a text field where they can input their own country. It works on the front end sign up form properly, but for the users who don't have the country selected from the new dropdown need to select a country. I have the dropdown on a front end profile form, however when the user "updates" their profile if they don't choose the country it just resets.

For example, I signed in and my country is set to USA and i go to my account to update my password, it resets what's selected on the countries dropdown.

I would like to show the County dropdown for the users who hasn't selected their countries and if the user already selected their country to just show the value they selected.

The code below is the code for the select.

{% set dropdownField = craft.fields.getFieldbyHandle('country') %}
<label for="country">Country</label>
<select class="form-control" id="country" name="fields[country]">
    {% for option in dropdownField.settings.options %}
        <option value="{{ option.value }}" >{{ option.label }}</option>
    {% endfor %}
</select>

You need to check the currentUser country if it's the same as the option value -> select the option

<option {{ currentUser.country.value == option.value? 'selected' : '' }} value="{{ option.value }}" >{{ option.label }}</option>


Set navigation menu item to active for child pages Currently we're highlighting the active page in our navigation by having a structure of menu items with a "menuLink" field and comparing that to the current entry uri. Something like this:

{% nav link in Menu %}

        {% if link.menuLink|length %}
            {{ link.title }}
        {% else %}
            {{ link.title }}
        {% endif %}

{% endnav %}

However, this doesn't work for children of structures or channels. We could change the if statement to look for the entry.uri OR the entry.section as below but obviously that only works if the section/channel has the same name as the link.slug:

{% if link.slug == entry.uri or link.slug == entry.section %} class="active"{% endif %}

I searched through the previous questions but all the answers to this problem seem to involve reading a section of the URL but we want to be able to control the URLs and have some structure children have a top level URL rather than a /structure-name/{slug}

If we could have a field on the structure itself to say which menu item to highlight then you could just say something like

if entry.section.type == channel or structure then active menu item = entry.section.menuItem

but you can't have a field on a structure/channel as far as I'm aware?

Does anyone know of a way of solving this problem without the use of URL segments?

Try using:

   {% set pageIsActive = (page.id == entry.id) %}

and then testing for that in your if statements.

This article covers pretty much every eventuality when it comes to classes and navigation and should help you achieve the markup you are after.


Craft doesn't recognize Snipcart plugin I'm following this tutorial (Managing Your Craft Inventory Using Snipcart Webhooks) and have downloaded the repository from GitHub and cloned. The folder was created without inconvenient but is still not recognized in the admin dashboard

You need to rename that snipcart-craft-webhooks-plugins folder to snipcartwebhooks in order for Craft to recognize it.


Trouble running a plugin console command I'm trying to get a basic console command for my plugin to run but not having much luck. I have created a folder called consolecommands inside my plugin directory and have created a file called AcmeNotificationsCommand.php.
In this file I have:
namespace Craft;

class AcmeNotificationsCommand extends BaseCommand
{
    public function actionHello()
    {
        echo "hello";
        return 0;
    }
}

From the console I am running /Users/dave/acme/craft/app/framework/yiic acmenotifications hello
But yiic comes back and says:
The following commands are available:
- migrate
- shell

So I guess it's not picking up my new console command.  What am I missing?
Update:
It occurred to me that maybe I was running the wrong yiic file since I could not see the Querygen command that is in the app/consolecommands directory as expected.
So instead I tried running /Users/dave/acme/craft/app/etc/console/yiic to see what commands were available and I got the following error:
0 /Users/dave/code/acme/craft/app/Craft.php(397): CComponent->__call('getTranslatedBr...', Array)
1 /Users/dave/code/acme/craft/app/Craft.php(397): Craft\ConsoleApp->getTranslatedBrowserLanguage()
2 /Users/dave/code/acme/craft/app/etc/db/DbConnection.php(57): Craft\Craft::t('Craft can???t c...')
3 /Users/dave/code/acme/craft/app/framework/base/CModule.php(387): Craft\DbConnection->init()
4 /Users/dave/code/acme/craft/app/etc/behaviors/AppBehavior.php(41): CModule->getComponent('db')
5 [internal function]: Craft\AppBehavior->isInstalled()
6 /Users/dave/code/acme/craft/app/framework/base/CComponent.php(261): call_user_func_array(Array, Array)
7 /Users/dave/code/acme/craft/app/services/PluginsService.php(89): CComponent->__call('isInstalled', Array)
8 /Users/dave/code/acme/craft/app/services/PluginsService.php(89): Craft\ConsoleApp->isInstalled()
9 /Users/dave/code/acme/craft/app/etc/console/ConsoleApp.php(53): Craft\PluginsService->loadPlugins()
10 /Users/dave/code/acme/craft/app/framework/base/CApplication.php(165): Craft\ConsoleApp->init()
11 /Users/dave/code/acme/craft/app/framework/YiiBase.php(121): CApplication->__construct('/Users/dave/cod...')
12 /Users/dave/code/acme/craft/app/etc/console/yiic.php(76): YiiBase::createApplication('Craft\ConsoleAp...', '/Users/dave/cod...')
13 /Users/dave/code/acme/craft/app/etc/console/yiic(4): require_once('/Users/dave/cod...')
14 {main}%

I also noticed a similar error when looking at the databaseimportexport plugin. Not sure if this is a bug or whether I am still doing something wrong?

Sounds like you haven't enabled the plugin from Settings->Plugins.

Once you do that, yiic will register your plugin's custom command.


Save Entry Data as CSV and Email it to the Author / Logged in User I am trying to email some Entry data that they have created in CSV Format to the author/logged in user. I have a controller setup with a frontend form posting an action to the controller:

public function actionSendCSV(){
 $this->requirePostRequest();

 $entryId = craft()->request->getParam('entryId');
 $entry = craft()->elements->getElementById($entryId);

 $user = craft()->userSession->getUser();

 if ($user->id != $entry->getAuthor()->id) {
     HeaderHelper::setHeader(array('status' => 404));
     craft()->end();
 }else{
   $list = array(
     //This is test data I'll construct the entry data here
    "Peter,Griffin,Oslo,Norway",
    "Glenn,Quagmire,Oslo,Norway");
    $file = fopen("test.csv","w");
    foreach ($list as $line){
      fputcsv($file,explode(',',$line));
    }

    $email = new EmailModel();
    $email->toEmail = $user->email;
    $email->subject = 'Your CSV';
    $email->body = 'How you doin, {{ user.name }}?';

    // Im not really sure what to do next here - do I save the CSV as an asset and then link it here?
    $email->addAttachment('path/to/csv/', 'name in e-mail.csv', 'base64', 'text/csv');

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

Is this the best way to handle this or should I save the entry data as CSV to my assets folder(Perhaps create a folder just for that user in the process to store all exports from them?) and send a link to users? If so what is the best method to achieve this?

Thanks!

For this purpose there is not such a thing like a "best" way. Every thing has advantages and disadvantages. Depending on your goal you should decide what fits best for you.

I personally prefer to have my files attached to the email so I can be sure I actually have the file on every device and I can redownload it every time. Other people might say it's better to just have a link for whatever reasons.

So I would create a temporary file and attach it to the mail like you do. Make sure to name each file separately. If you have really large entries (that need more time to generate the csv) and two authors click the button at the same time they could eventually overwrite each other. So it might be a good idea to include the author ID or something in the filename. You can delete it afterwards.

If you want to keep these files you could store them as Craft assets but i don't think this is necessary for your purpose. You could create a record if you like to track the activities. So if you need to see how many authors used that download how often you can insert it into your database.

However, the more interesting thing is how to fetch the entries and fields.
Btw you know you have to parse the body content in order to replace the twig tokens?

Edit
You could use this function

 /**
 * Send Email
 *
 * @param $message string
 * @param $subject string
 * @param $mail string
 * @param array $attachments
 * @return bool
 */
public function sendMail($message, $subject, $mail, $attachments = array()){
    $adminEmail = craft()->systemSettings->getSetting('email', 'emailAddress');
    $email = new EmailModel();

    $email->fromEmail = $adminEmail;
    $email->replyTo = $adminEmail;
    $email->sender = $adminEmail;
    $email->fromName = craft()->getSiteName();
    $email->toEmail = $mail;
    $email->subject = $subject;
    $email->htmlBody = $message;

    if(is_array($attachments) && count($attachments)){
        foreach($attachments as $attachment){
            $email->addAttachment($attachment['path'], $attachment['name']);
        }
    }
    return craft()->email->sendEmail($email);
}

with

$attachment = [
    [
        'name' => "The name you want to display.csv",
        'path'  => $file // path/to/your/file
    ]
];

$subject = "Your CSV";
$email = $user->email;;
$message = craft()->templates->render('path/to/template', array(
    'username' => '...',
    // .....
));
if($this->sendMail($message, $subject, $email, $attachment)){
    // message send
}else{
    // some errors
}


How to change the display order of columns in Entry List view? When adding a custom column to an Entry List view using the modifyEntryTableAttributes hook, how would you also set the display order of columns?

You need to reorder the $attributes array to do this. You can do this in various ways, here is how I would do it depending on the position you wanted for the new column:

public function modifyEntryTableAttributes(&$attributes, $source)
{
    if ($source == 'section:3')
    {
        // insert column in first position (using array_merge)
        $attributes = array_merge(array(['id'] => Craft::t('ID'), $attributes);

        // insert column in fourth position (using array_splice)
        array_splice($attributes, 3, 0, array('id' => Craft::t('ID')));
    }
}


How do you deploy Craft 3 on Heroku with Postgres? I'm relatively new to Craft 3, and am able to run Craft locally with a Postgres db and Valet as my server. When I try to deploy to Heroku, I run into issues with (I think) Postgres.

Background

I tried setting up Craft to work with Heroku by following this guide (see the "Publishing" section near the bottom of the guide). I found that if I just run a heroku create and then push my local branch to the remote server, I get an "Internal Server Error" when loading the remote site on Heroku.

Instead, I created an app.json file as per this guide by @edenspiekermann. Then I run https://heroku.com/deploy with arguments to create the Heroku app, and this allows me to access the Craft admin page at /admin/install on the remote server.

Following the first guide, I also push my local Postgres database to Heroku with heroku pg:push DB_NAME DATABASE_URL --app HEROKU_APP_NAME.

Questions

-How does Heroku know the right DATABASE_URL to use in /config/db.php? Locally, that variables comes from .env which is not pushed to my repo or Heroku.

-Why does Heroku show an internal server error if I just push my local branch to the remote server (whereas creating a Heroku app with https://heroku.com/deploy works)?

My db.php file:

preg_match('|postgres://([a-z0-9]*):([a-z0-9]*)@([^:]*):([0-9]*)/(.*)|i', getenv('DATABASE_URL'), $matches);

$user = $matches[1];
$password = $matches[2];
$server = $matches[3];
$port = $matches[4];
$database = $matches[5];

return [
  'driver' => "pgsql",
  'server' => $server,
  'user' => $user,
  'password' => $password,
  'database' => $database,
  'schema' => getenv('DB_SCHEMA'),
  'tablePrefix' => getenv('DB_TABLE_PREFIX'),
  'port' => $port
];

My Procfile for Heroku:

web: vendor/bin/heroku-php-apache2 web/

My .env file:

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

# The secure key Craft will use for hashing and encrypting data
SECURITY_KEY=""

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

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

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

# The database password to connect with
DB_PASSWORD=""

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

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

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

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

DATABASE_URL="postgres://atc:@localhost:5432/blogdb"

DEFAULT_SITE_URL="https://landing-page.dev"

Error I receive when navigating to homepage on Heroku after I've pushed my local Postgres db to Heroku remote:

HTTP 503 – Service Unavailable – craft\web\ServiceUnavailableHttpException

Found out that there are a variety of Config vars in Heroku you need to set that match your local .env file. In particular:

ENVIRONMENT
SECURITY_KEY
DB_SCHEMA

Edit 10.1.19 Wrote this tutorial on how to get Craft 3 up and running on Heroku.


Register JS files at the end of the body tag in the Control Panel I would like to add my own external JS sources at the very end of the body tag in the Craft control panel.

I've already tried using:

{% do view.registerJsFile("<CDN_URL>", {position:3}) %}

according to https://www.yiiframework.com/doc/api/2.0/yii-web-view#registerJsFile()-detail, but Craft is always adding its own JS sources after mine.

Any help would be appreciated!

You can set the CP asset as depency then it will be loaded after it

{% do view.registerJsFile("<CDN_URL>",{
    depends: 'craft\\web\\assets\\cp\\CpAsset',
    position:3
}) %}

That's because Yii2 will always register Bundles without any dependencies first / in the order they are defined. If you require the CpAsset it will be loaded afterwards


Craft CMS & React JS Researching this online and not having much luck if anyone has done this before.

How would one get the content from the CMS to update the FE and also create new pages / modules as a normal CMS would allow you to do?

Little confused on this.

You could take a look at the Element API to help bridge the gap between your React front-end and your Craft back-end. That will at least help you with getting data out of Craft.

As far as creating new pages and modules you'd use Craft's Control Panel (CP). You're going to have to take a look at the Craft Documentation in particular Sections & Entries.


How do you create a custom button field type (with js includes) for customizing the CP? I'm trying to figure out how to integrate Stripe into the CMS more natively, and a thought occurred to me. Would it be possible to create a fieldtype that was just a button (i.e. no data being stored) with its own javascript?

This would potentially allow you to add a lot of customization and functionality just by adding the button fieldtype to the field layout (rather than having a global javascript file throughout the CP) — like silently submitting data to an external service, handling the response, dynamically rewriting the CP form submit action temporarily to point to a custom controller, etc.

Bad idea? Or worth investigating?

I thought I would report back with the good, the bad, and the ugly.

The good It is very possible (and quite easy) to create a field type button element, and include your own custom javascript as is explained in the fieldtype plugin documentation. Setting the defineContentAttributes to return false will prevent columns from being created in the database. And name, value variables are not even needed in this case in templates->render array. Here is the basic MyPlugin_CustomButtonFieldType.php:

class MyPlugin_CustomButtonFieldType extends BaseFieldType
{
    public function getName()
    {
        return Craft::t('Custom Button');
    }
    public function defineContentAttribute()
    {
        return false;
    }
    public function getInputHtml($name, $value)
    {
        craft()->templates->includeJsResource('myplugin/js/custombutton.js');
        return craft()->templates->render('muplugin/fieldtypes/CustomButton/input', array(
        ));
    }
}

And in the fieldtype template file (for a default CP craft looking button):

<input id="custombtn" type="submit" class="btn submit" value="{{ 'Do Something'|t }}" >

So far so good. Imagine the possibilities!

The Bad It is basically impossible (as far as I can tell) to over-write the default actions (i.e. action/saveEntry) via javascript as it is often dynamically inserted into the DOM via javascript depending on if you're using the command+s save shortcut or the save button sub-nav, etc. So replacing the default controller action, doesn't look like an option.

Update: It does look like you can prevent the default form submission, though. And then perhaps write your own .click() listener.

$('#entry-form').submit(function(event) {
    event.preventDefault();
    return false;
}
$('input.save').click(function()){...}

The Ugly It is possible to prevent fields from getting saved to the database (i.e. credit cards, and cvc codes) by simply removing the 'name' attributes from the fields, using something like:

jQuery(function($) {
     // prevent the form from saving credit card and cvc codes
     $('input[name*="creditCardNumber"]').removeAttr('name');
     $('input[name*="cvc"]').removeAttr('name');
}

But it's pretty much a hack job and not very pretty.

So, custom field types with buttons and javascript look like a very easy and very powerful way to customize the CMS. And so far it seems pretty easy to send data via javascript to remote services, retrieve tokens, forward the token via ajax to a custom controller to get processed, saved and result returned.

Messing with the default actions on the other hand, not such a good idea.


Trailing slashes with Nginx and Craft What's the best way to redirect to a trailing slash in Nginx with Craft CMS? I've seen some advice for Apache .htaccess, etc, but not Nginx. For those curious, here's why I might want to do this: To slash or not to slash.

NYStudio107 recommendations advise removing the trailing slash, but since we were formerly on Wordpress and had a trailing slash to begin with, I want to be consistent with the past history in Google Analytics.

After some digging, there appear to be two ways that avoid hitting the admin and url query strings.

The first, (and apparently better one, as 'if is evil' according to nginx) uses location handlers:

# 301 Redirect for trailing slash
location ~ ^([^.\?]*[^/])$ {
  try_files $uri @addslash;
}

# 301 Redirect for trailing slash
location @addslash {
  return 301 $uri/$is_args$args;
}

# Root directory location handler
location / {
    try_files $uri/index.html $uri $uri/ /index.php?$query_string;
}

The second, more evil one that uses an if statement:

if ($request_uri !~ "^/admin")
{
    rewrite ^([^.\?]*[^/])$ $1/$is_args$args permanent;
}

I included the context of the root location handler in the first solution so that you can combine it with your existing root location handling setup. I'm currently leaning on a lot of NYStudio's work (a truly incredible contributor to the open source ecosystem of Craft) with FastCGI, location handlers for foreign languages, etc and both of these solutions work with it.

The first also works with query strings, if a user visits a URL either with or without a trailing slash. For example:

This: www.domain.com/page?string=234
Will go to this: www.domain.com/page/?string=234
And this: www.domain.com/page
Will go to this: www.domain.com/page/

Interestingly, if you use query_string instead of is_args for the return url, it will rewrite it wrong. Only is_args worked in my experience.


Supersort - Sort multiple variables together I'm trying to sort my commerce orders by 2 variables, one being in the order loop, and the second being within the lineitems. I want to order by the lineitem variable first, and THEN the order variable. Something a bit like this:

Order - Group Name
LineItem - Product ID

I want to order by custom product ID asc and then Group Name alphabetically. So it would go a little like this:

ID: 1, GroupName: Aaa
ID: 1, GroupName: Bbb
ID: 2, GroupName: Aab

etc...

The current code I have is this:

{% set orders = craft.orders().limit(null).all() %}
{% set orders = orders|supersort('sortAs', '{{ object.groupName }}') %}

{% for order in orders %}
    {% for item in order.lineItems %}
       {{ item.purchasable.product.customProductId }}
    {% endfor %}
{% endfor %}

Ideally, I'd need to do something along the lines of:

{% set orders = orders|supersort('sortAs', '{{ item.purchasable.product.customProductId }} {{ object.groupName }}') %}

But that obviously doesn't work.

Managed to do this by putting it all into an array:

{% set productID = [] %}
{% set orders = craft.orders().limit(null).all() %}

{% for order in orders %}
    {% for item in order.lineItems %}
        {% set productID = productID |merge([ {
            'productId' : item.purchasable.product.customProductId,
            'groupName' : order.groupName
        }]) %}
    {% endfor %}
{% endfor %}

{% set productID = productID | supersort('sortAs', '{{ object.productId }} {{ object.groupName }}') %}

{% for theID in productID %}
    {{ theID.groupName }} - {{ theID.productId }}
{% endfor %}


Getting to grips with errors and flash messages As a newbie to Craft and Craft Commerce. I wondered if someone could explain the difference between all these error codes that I have seen either in the docs, this forum or the templates and when they get set and when I should use each method in which situations? Apologies if this is a broad question...

{% if errors is defined %}

        {% for error in errors %}

{{ error }}

        {% endfor %}

{% endif %}

{% if errorMessage is defined %}

{{ errorMessage }}

{% endif %}

{% if model and model.getErrors('firstName') %}
   {{ model.getErrors('firstName')|join }}
{% endif %}

It's hard to be more specific without some more context for each of the snippets you post, but:

{% if errors is defined %}

        {% for error in errors %}

{{ error }}

        {% endfor %}

{% endif %}

That's checking if a variable named errors has been passed into the template, and if so it assumes it's an array and loops through the array to display each error in an unordered list.

{% if errorMessage is defined %}

{{ errorMessage }}

{% endif %}

That's checking is a variable named errorMessage has been passed into the template and if so it assumes it's a string and just displays the single error message.

{% if model and model.getErrors('firstName') %}
   {{ model.getErrors('firstName')|join }}
{% endif %}

That's checking if a variable named model has been passed into the template and assumes it's an instance of BaseModel.  Then it calls the getErrors method of the class passing in firstName as a parameter to specifically check if any errors have been set on its firstName attribute.  If so, it will take that array of errors and display them using Twig's join filter.


In the entries listing (backend), how can I disable the preview button in Craft 3? I'm building a single page site, so there wont be a page for each entry. How can I disable the preview (world) button for each entry? I'm using the structure section type.

You'll want to leave the Entry URI Format field in the section settings blank. That will disable the "world icon" in the entry index as well as the Live Preview and Share buttons on the individual entry edit pages, as well as several other things (for example, there will be no {{ entry.url }} available in the templates).


Password should fail on front-end registration form Update For anyone else having a braindead moment, registration form errors only display for password when logged out. If you're logged in as admin they won't display.

User posted even though using an empty password. According to this post and this form template an empty password box (or less than 6 characters) should fail and return an error yes?

        Password

        <input id="password" class="form-input" type="password" name="password">
      6 characters or more — keep it secret, keep it safe.

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

    <input class="btn btn-primary" type="submit" value="Register">
    </form>

Screenshots:

Registration form errors only display for password when logged out. If you're logged in as admin they won't display.


Cannot see local or s3 image asset source I have the correct image asset source for S3 and also a local folder. Neither folder contents show (they were previously) and I see an "unknown error occurred" popup. I've tried turning off image transforms, increasing my PHP memory limit and simplifying my templates but I haven't had any luck

For anyone else experiencing this issue, there wasn't actually any error shown in the Craft log file. Craft was trying to index the S3 access log files on the bucket and treating them as image files. Reindexing images didn't solve the issue either but I got my images back by deleting all entries from the craft_assetfiles table for files have the dateModified field set to NULL (these were not image files but Craft had added them to the table). [Solved by Craft Support]


Get Entry by Specific ID I have a Freeform Email Notification getting sent out where I'm trying to fetch the ID of a specific entry that the Email is associated to. The emails are working, yet the entry that it's returning is completely wrong - yet the ID is right. I don't have a clue what's going on!

{% set entrynumber = submission.entry %}
{% set proposalEntry = craft.entries.id(entrynumber).first() %}
{{ entrynumber }}
{{ proposalEntry.id }}
{{ proposalEntry.title }}
{{ proposalEntry.author }}
{{ proposalEntry.proposalCampaign }}

The above produces the following:

441
471
Domino's Pizza New Yorker range
admin

As you can see, it's the wrong entry that it's calling? It looks like it's just using the latest entry?

I'm guessing that 'submission.entry' is not really the same as entry id. If you are using the connections method with Freeform then the data is stored as json against the form id. I think we need more info about how this bit works: "the ID of a specific entry that the Email is associated to"


Using search to display entries based on a value in a number field I'm trying to return results based on a year stored in a custom field. For example, returning entries with a model year greater than 2006 and less than 2009. Is there a search syntax to support this?

For example: for entry in craft.entries.section('equipment').search(modelYear: > 2006 && < 2009) …

You can do a certain amount of logic in the ElementCriteriaModel syntax. I think this will work:

{% set entries = craft.entries.section('equipment').modelYear('and, > 2006, < 2009') %}
{% for entry in entries %}
  ...
{% endfor %}


German special characters like umlauts (ä, ö, ü) are not converted correctly with convertFilenamesToAscii Filenames with German special characters are not converted correctly with convertFilenamesToAscii, e.g. ä, ö, ü are converted in a, o, u in contrast to ae, oe, ue in slugs with limitAutoSlugsToAscii.

This was a bug and has now been fixed in Craft 3.5.12.1
https://github.com/craftcms/cms/issues/6923


Craft 3 protecting a page with a password? I have used the Guest Entries to create a plugin where anonymous users can create a entry. I have a password field on each entry. Now I want the guests who have created the entry to be able to login with this password and edit the entry they created. I don't need user validation etc for this, just a single password. Is this possible in Craft 3?

I don't think this is possible with Craft out the box, and would require a module / plugin to add this functionality.

Firstly to write the password to the database and encrypt it, so it's not stored in plain text.

Then it would just be a case of having a controller (https://docs.craftcms.com/v3/extend/coding-guidelines.html#controllers) that checks this password from a form submission and unlocks the ability to edit the entry again.


currentUser gets cached I'm having a problem with navigation that seems to get cached.
If the page is loaded by someone who is not logged in, it shows the login button in the navigation (and it should).
Once the user is logged in and returns to that specific page (by clicking a link on the site), the page still shows the login button.
Only when the user manually refreshes the page, the login button gets replaced by the users name.

The template code uses the currentUser variable, which is never overwritten anywhere else.
There's no cache blocks used on the website, and the cache-control header is set to no-store, no-cache, must-revalidate
{% if currentUser %}
    {% if currentUser.firstName != '' and currentUser.lastName != '' %}
        {{ currentUser.firstName }} {{ currentUser.lastName }}
    {% else %}
        {{ currentUser.email }}
    {% endif %}
{% else %}
    {{ loginPage.title }}
{% endif %}

It turns out the cache-control headers weren't coming through at the end.
I solved the problem by adding all the right headers.
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "Wed, 12 Jan 1980 05:00:00 GMT"


How can I set a custom URI for the confirmation link of account email update from a front-end form? I have a front-end form to update user's email address, like this example:

<form method="post" accept-charset="UTF-8" enctype="multipart/form-data">
    {{ csrfInput() }}
    <input type="hidden" name="action" value="users/save-user">
    <input type="hidden" name="userId" value="{{ currentUser.id }}">

    New email address
    <input type="email" name="email" value="" id="newEmail">

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

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

Once the form is submitted, Craft send a system message to the user email address, with a confirmation link. Once this link is clicked, the user is redirected to the root URL of the front-end website.

I changed the activateAccountSuccessPath, but whereas it works during account activation, it doesn't works during account email update.

Example:

'activateAccountSuccessPath' => array(
    'en' => 'my-account',
    'fr' => 'mon-compte'
)

Or:

'activateAccountSuccessPath' => 'my-account'

I also tried to enable / disable the autoLoginAfterAccountActivation setting, but the redirection is still not working. Even is user is already logged in, or if he is logged out.

I also checked the Craft logs, but I there's no error, no missing template, etc. ... nothing.

How can I set a custom URI on this link?

I can't think of a clean way to do this because of this function

public function actionVerifyEmail(): Response
{
    // ..
    // snip
    // ..
    if (Craft::$app->getUsers()->verifyEmailForUser($userToProcess)) {
        // ..
        // snip
        // ..
        // Redirect to the site/CP root
        $url = UrlHelper::url('');  // <---- this is where we are
        return $this->redirect($url);  // ALWAYS redirect to root page
    }

    return $this->renderTemplate('_special/emailtaken', [
        'email' => $userToProcess->unverifiedEmail
    ]);
}

A clean way to achieve this is:

Handle it entirely on your own -> custom controller + custom service, send the mail manually
Create a custom route to you'll only take care about activating them and overwrite the actionVerifyEmail - unfortunately you can't replace the controller via Dependency Injection
Create a feature request and hope Pixel and Tonic will be kind enough to create a config variable / event to overwrite this value


Fetch target entries that have been linked through an Entries field I have a section Posts that has an Entries-type field called Authors that can be linked to one or more entries in section called People. To make a filter for my posts index, I need to fetch all the People entries that have been linked to any post via the Authors field, but I can't wrap my head around how to do this.

Any ideas appreciated!

You first need to query for all post entries and then query for the authors that are related to a post. You can use the ids() method to get just the author’s element IDs, which is a lot quicker than find().

{% set allPostIds = craft.entries({
    section: 'posts',
    limit: null,
}).ids() %}

{% set people = craft.entries({
    section: 'people',
    relatedTo: {
        sourceElement: allPostIds,
        field: 'people',
    },
}) %}


Displaying the Meta Description I am new to Craft.

Do I need to change any files to display the Description that I have set up for http://viviendasdeprimera.com/eventos/proyectos-de-casas-en-arraijan ?

Many thanks,

Mike

Mike: yes you do. It sounds like you had your site built by another developer?

Unlike other CMS, everything that displays on your website in Craft is custom built. The gist is you setup a bunch of fields on the backend (Craft's "control panel")—which is probably what you did. Think of the control panel as simply an interface to database.

However, those fields won't display anything on the front-end. What is output is controlled by templates. If you're used to something like WordPress, Craft basically only has one "theme" and it's not accessible in the control panel.

In short, you basically need to tell Craft where to spit it out.  Depending on how your site was built, it's probably in a _layout.html file inside the craft/app/templates folder.

If your field's name is Meta Description, you could add it to the template in the appropriate place  somewhere like:

{% if entry is defined and entry.metaDescription is defined %}
  <meta name="description" content="{{ entry.metaDescription }}">
{% endif %}

In the control panel, the field would need to added to any section you want to use the Meta Description. If you've added that field to a section, the field will be output.

If you need more help with this, check out the Craft documentation, Mijingo's  lessons on Craft, or hire a Craft professional to help you out.


SEOmatic page parent? I was wondering if it is possible to create a SEO Title Source in SEOmatic where the page title is output and then the parent/section page title e.g.:

{entry.title} | {{ entry.parent.title }} | Company Name

(The entry.title works but am not sure if its possible to get a parents page title)

Thanks
Malcolm

Yep, you should definitely be able to do what you want.

What I do is I test the code in the actual Twig template used to display the page, and then once I have it working, I paste it into the SEOmatic field, and add object. in front of the entry.

e.g.: If this gives you the results you want in the template:

{{ entry.title }} | {{ entry.parent.title }} | Company Name

Then when you paste it into SEOmatic's CP fields, it'd look like this:

{{ object.entry.title }} | {{ object.entry.parent.title }} | Company Name

I find that this makes it easier to debug.


Set Structure Parent when creating Entry in Plugin I have Structure-type Section for entries and want to pragmatically populate a large list of multi-tiered entries.

I see you can create an entry like:

$entry = new EntryModel();
$entry->getContent()->title = 'New Page';
$entry->getContent()->body = null;

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

What I want to do is add the parent(s) of the entry, something like:

$entry = new EntryModel();
$entry->getContent()->title = 'New Page';
$entry->getContent()->body = null;

// this entry would be a child in order of Sports -> Tennis -> This Entry
$entry->getContent()->parent = sports->tennis;

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

Is there a way to do something like that?

This question is old, but the solution is:

// look up parent with a ElementCriteriaModel

$parentCriteria = craft()->elements->getCriteria(ElementType::Entry);

$parentCriteria->search  = 'slug:'.$parentSlug; // whatever you have

$parent = $parentCriteria->find()[0];

$entry = new EntryModel();
$entry->sectionId = $section;

$entry->parentId = $parent->id;

...


Sprout Forms or Craft not sending email to Craft user email addresses Is there anything in Sprout Forms or Craft that prevents an email being sent to any registered Craft user email address but not other email addresses not in the Craft user list?

I have a really simple one field form that sends a notification to two email addresses: the one in the submitted form field, as well as the one in the CP Sprout Forms notifications field.

A weird thing is happening. If I use an email address that is not belonging to a Craft user (either as the typed in notification address or the {email} one) the email is sent (according the server logs) and received. If I use an email address belonging to a  Craft user the email is not sent from Craft (doesn't even register in the server logs).

(The simple form is trying to distil the problem down - it is occurring on all my forms, and was working before but has stopped, possibly the same time as a server change. The PHP mail() function works to said email addresses. I am using latest versions of Craft and Sprout Forms on PHP 7.)

Edit: I can swap email addresses in and out of the user list so when they belong to a user no email is sent, and when they are removed from the user list, the email is sent. This suggests there is nothing wrong with the email address per se or the route through the system, but purely the fact that it is a Craft user email address.

Edit2: When sending to a craft user email address the following craft.log error is made:
Email error: Could not execute: /bin/mini_sendmail (etc)
This doesn't happen when a non-craft user email is used. So suggests to me Sendmail is not properly set up (but why then do other emails get through fine).

As mentioned in the comments, this is likely an email configuration issue and Brad's comment should be taken to heart:

  both sendmail and PHP's mail are notoriously unreliable and shouldn't be used in production environments

Craft should not be treating user emails differently than non-user emails and Sprout Forms isn't doing anything unique when it sends notification emails, it's just piggybacking on what Craft is doing.

Sending your email through a service like Mailgun (or any similar service) will give you more visibility into what's happening and what you may need to troubleshoot. Sprout Email has a Sent Email Element Type that you can enable to help troubleshoot some email deliverability issues on the Craft side of things.

For two good overviews on troubleshooting email errors in Craft, see:

https://craftcms.com/support/troubleshooting-email-errors - Craft Docs
Troubleshooting and debugging errors in PHP - Straight Up Craft

Another direction to consider when troubleshooting an error like this may be to look closer at the From headers and what emails you are sending to. Is it really just Craft Emails vs non-Craft Emails or could there be other patterns? For example, maybe the emails that aren't being received are all gmail addresses. In some cases, if you are sending to a gmail address you own from a gmail address you own, Google may suppress the email from appearing in your inbox.


How do I (also) cycle a class on a Matrix block? I think I am doing exactly the same as here but I only get the "even" class at each iteration.

{% for block in entry.articlebody %}

    {% set index0 = loop.index0 %}

    {% switch block.type %}

        {% case 'heading' %}

{{ block.heading }}

        {% case 'text' %}

{{ block.text }}

    {% endswitch %}
{% endfor %}

The loop.index0 variable will be incremented for each block, regardless of type, so assuming every other block is a header, it's not surprising that the cycle method prints "even" for every text block.

I think what you need is a different variable which only increments whenever you hit a text block (note that this variable should be declared outside the for loop):

{% set textIndex = 0 %}

{% for block in entry.articlebody %}

    {% switch block.type %}

        {% case 'heading' %}

{{ block.heading }}

        {% case 'text' %}

{{ block.text }}

            {% set textIndex = textIndex + 1 %}

    {% endswitch %}
{% endfor %}


In the CP, How to make images bigger when the users select images? In the Control Panel, when users are selecting an image for the asset field, the thumbnails are too small in the popping up image modal. Is there any way to make the images bigger?

If you're running Craft 3, you can click an asset and then hit SHIFT + SPACE to open a Lightbox with the image.


Change field arrangement from the entries page In ExpressionEngine you can rearrange the field types from inside the entry. I was wondering if there was any feature like this in Craft? I've got a lot of different types of entries so it's a pain to jump back and forth between sections and entries to see if the organisation is correct, plus it would just be easier to organise if I can see what the final product would be.

No, that's not possible with Craft at the moment (2.4). You'll have to use the Field Layout Designer from Settings -> Sections -> {Section} -> {Entry Type} to manage your fields and tabs.

You could always add a feature request if you feel this is something that should be included in the core.


Refreshing meta data when using AJAX page transitions I have created AJAX page transitions based on:

https://designbycosmic.com/journal/craft-cms-ajax-page-transitions-with-history-pushstate

It's all working nicely, the main content of the site (everything except the header) is loaded through ajax with a page transition using velocity.js.

My question is how would I go about getting all the metadata (or intact any of the information stored in  to refresh for each page. At the moment the meta data is stuck with whatever is there when the browser loads.

I know this isn't specifically craft but any help would be appreciated.

Scott

You'll need to send the new pageview to Google Analytics manually on your ajax success. You'll want to read the Google documentation page, but it can be as simple as added the following line where ga_page is the new url:

ga( 'send', 'pageview', ga_page );


Customizing the destination after user activates the account I would like to ask about activation e-mail which is sent to new user.

Once the user clicks the link, it redirects to homepage.
Is it possible to change the destination?
I would rather like to make it to login page.

Craft support desk helped me, so I would like to share it.

The destination can be set with this. Add it on your general.php.

'activateAccountSuccessPath' => 'users/login',

Please be sure to change 'users/login' to the destination you want to set.

If it does not works, add this;

'verifyEmailSuccessPath' => 'users/login'


Default Upload Location for asset fields on a User...? when setting a Default Upload Location for a field that’s attached to a User, what’s the variable to use that would ensure the file is uploaded to the User I’m editing’s account in the back end, and not my admin user account - which is what {{currentUser.username}} does?

I haven't been able to find out and everything I've tried hasn't worked. e.g., Could not resolve the subpath “{user.username}”. And {{ user.username }} uploads to a folder for my admin account.

Assuming you want the folders to be named after the users' IDs (since they won't change), the subpath should be {id}.


Check if child entries exists I'm pulling in entries which are the descendant of the current entry id.

This is an example of my structure: Your Adventure > Honeymoon > A trip entry.

The below code is being used on the Honeymoon entry to list any trip entries that are children of the current page.

The below code is working fine apart from the if statement I'm wrapping it all in as I don't want any of the wrapping divs if there are no child pages within 'Honeymoon Trips'.

{% if entry in craft.entries.section('yourAdventures').descendantOf(entry.id)  %}

Available {{ entry.title }}

            {% for entry in craft.entries.section('yourAdventures').descendantOf( entry.id).find() %}

            ...

            {% endfor %}

{% endif %}

If I figured out correctly what you want to do - this should do the trick:

{% if entry.children | length  %}

Available {{ entry.title }}

                {% for child in entry.children %}

{{ child.title }}

                {% endfor %}

{% endif %}

entry.children is an alias for entry.getDescendants(1) which returns ElementCriteriaModel


How to update Matrix field on frontend for user profile I have used the following code to allow our users to update their own profile. Everything works fine apart from not being able to update existing Matrix entries.

New Matrix field entries work fine. Can anyone spot the mistake I've made?

          <form method="post" accept-charset="UTF-8">
          {{ getCsrfInput() }}
          <input type="hidden" name="action" value="users/saveUser">
          <input type="hidden" name="redirect" value="/account/profile">
          <input type="hidden" name="userId" value="{{ currentUser.id }}">

          First Name
          <input type="text" id="firstName" name="firstName" value="{{ currentUser.firstName }}">

          Last Name
          <input type="text" id="lastName" name="lastName" value="{{ currentUser.lastName }}">

          Telephone
          <input type="text" id="telephone" name="fields[telephone]" value="{{ currentUser.telephone }}">

Additional Contacts

          <input type="hidden" name="fields[alternativeContacts]" value="">

          {% for block in currentUser.alternativeContacts.type('contact') %}

            <input type="hidden" name="fields[alternativeContacts][{{ block.id }}][type]" value="contact">
            <input type="hidden" name="fields[alternativeContacts][{{ block.id }}][enabled]" value="1">

            <input type="text" name="fields[alternativeContacts][{{ block.id }}][fields][firstName]" value="{{ block.firstName }}">
            <input type="text" name="fields[alternativeContacts][{{ block.id }}][fields][lastName]" value="{{ block.lastName }}">
            <input type="text" name="fields[alternativeContacts][{{ block.id }}][fields][telephone]" value="{{ block.telephone }}">
            <input type="email" name="fields[alternativeContacts][{{ block.id }}][fields][email]" value="{{ block.email }}">

            <button class="btn btn-xs btn-danger" data-action="delete-contact"></button>

          {% endfor %}

New Contact

            <input type="hidden" name="fields[alternativeContacts][new1][type]" value="contact">
            <input type="hidden" name="fields[alternativeContacts][new1][enabled]" value="1">

            <input type="text" name="fields[alternativeContacts][new1][fields][firstName]">
            <input type="text" name="fields[alternativeContacts][new1][fields][lastName]">
            <input type="text" name="fields[alternativeContacts][new1][fields][telephone]">
            <input type="email" name="fields[alternativeContacts][new1][fields][email]">

          <input type="submit" value="Save Profile">
      </form>

Turns out it was a validation issue, it works fine when you make the new contact's first+last name mandatory.


Type number form in textField for plugin I haven't found any fields that deal with numbers for a plugin. I've changed a forms.textField into a type:number which has seemed to work fine for the most part. But I can't find a way to keep someone from going under 0 or over 100. I've looked in vendor\craftcms\cms\src\templates\_includes and have come up empty.

I'm assuming I'll need to make a custom field type for this but if there is something I'd rather not reinvent the wheel.

  {{ forms.textField({
      label: 'Blanket Discount Percent',
      instructions: 'Set this if you want to offer a blanket discount to all businesses. Do not put in letters or decimals. (10 = 10%)',
      id: 'blanketDiscount',
      name: 'settings[blanketDiscount]',
      value: settings.blanketDiscount,
      type: 'number',
   })}}

I do have a rule for validation setup, I would just prefer to keep people in range at the front as well.

['blanketDiscount', 'integer', 'min' => 0, 'max' => 100],

Not tested yet.

{{ forms.textField({
        label: 'Number Field',
        id: 'someId',
        name: 'someName',
        value: '',
        min: 0,
        max: 100,
        size: 1,
        type: 'number',
        value: settings['someName']
    })
    }}

I think you can use min and max


Upload asset failed to open stream: Invalid argument When I try to upload an image, I am getting the following error:

imagepng(C:/wamp/craft/storage/runtime/temp/assets53ebcb012cffa3.92019251-temp.png): failed to open stream: Invalid argument (C:\wamp\craft\app\vendor\imagine\imagine\lib\Imagine\Gd\Image.php:691)

Do you know what is going wrong?

I'd check the permissions and make sure that Craft has write permissions to the craft/storage folder first.


Store form data with file upload in an asset source using Freeform I currently have a form that has an upload file fieldtype and this currently stores the file in an asset source in Craft. What I would like to do is attach some of the form submitted field data alongside the asset using fields within the Asset field layout.

Ideally I would like to store the Form Submission ID, Name and Email address.

Any ideas as to how I would go about doing this?

Thanks,

You could try to use Craft and/or freeform hooks https://solspace.com/craft/freeform/docs/events-and-hooks/#events-freeform-forms and fetch the assets related to the entry during the beforeSaveprocess, add field values of the submission to it and save it again. There are examples how to do this in Crafts documentation

Or the most flexible (and for me easiest) thing: create a custom controller that extends the freeform controller and add a few lines to attach those information to the asset.


Next / Prev and looping/cycling entries instead of reaching the end of the selected results Is there a way to be able to use entry.getNext(params) to return back to the first entry when you're viewing the last entry in the parameters?

With the result of looping/cycling through all entries and returning to the original.

If there isn't a "next" sibling, entry.getNext() returns null – in which case you can use Twig's default filter to set an alternative value (i.e. your first entry).

Untested, but something like this should work:

{% set nextEntry = entry.getNext|craft.entries.section('mySectionHandle').first() %}


Serialization of 'Closure' is not allowed I created a form on the frontend that allows users to upload their profile photos:

<form method="post" accept-charset="UTF-8" enctype="multipart/form-data">
    {{ csrfInput() }}
    <input type="hidden" name="action" value="users/save-user">
    <input type="hidden" name="redirect" value="users/{{ currentUser.username }}">
    <input type="hidden" name="userId" value="{{ currentUser.id }}">

    <input type="file" name="photo">
    <input type="submit" value="upload">
</form>

But I get the following error:

  Serialization of 'Closure' is not allowed from /Users/rain/dev/valet/tr3ndsideas/vendor/yiisoft/yii2-queue/src/serializers/PhpSerializer.php

Any ideas on how to fix this problem?

I found the problem which is because of a plugin called "Scout". I just update it and everything seems to be fine now.


Use Vue.js with Craft I want to build my first website with Vue.js but have difficulties how to start.
Craft and Vue.js both use {{ }} as delimiters, but I found out that I can change this for Vue. So to start, I tried the following in my JS file.

Vue.config.debug = true;
Vue.config.delimiters = ['${', '}'];

new Vue({
    el: '#content',
    data: {
        message: 'Hello Vue.js!'
    }
});

But the output I get is ${ message }

In the html file I have the following:

<div id="content" role="main">
    ${ message }
</div>

In the html file, I first load vue.js, then my script.
I use Vue.js v2.0.0-rc.6

Any idea how I can make this work?

I know the problem here is solved, but I thought I'd just leave a link to a pretty decent intro to using Craft and Vue 2.0 for future reference...

Using Vue 2.0 with Craft CMS

And specifically the part addressing the problem above:

It’s all about the mustaches

NOTE: I'm not the author of the blog post, just found it useful.


Best practice for collecting a response from a third party So I'm in the middle of creating a plugin that allows users to make payments with GoCardless. Once payment has been made on the GoCardless website the user needs to be redirected to a PHP script that will confirm the payment was all hunkie-dorie... but....

Where do I put this script? At the moment I've put it inside a folder that is inside the htdocs folder but I'm having problems calling craft()->plugin_name->confirmPayment() from this location as craft() is undefined here.

Help greatly appreciated, thanks!

After the payment has been made, you can have the response callback go to an anonymous action method on your plugin's controller.

The URL for that would look something like this:

http://mydomain.com/index.php/actions/myPluginHanlde/myPluginController/myPluginAction

From there you can perform any additional business logic (validation, record saving, etc.), and $this->redirect(''); to a success template.


Lingering artifacts of deleted Sprout Forms plugin causing queue failure for updating search indexes I noticed I had a task failure notification that I couldn't clear in my Craft 3 cp for updating search indexes. Found this in queue.log:

  2020-01-15 20:02:44
  [-][41673][-][error][craft\queue\QueueLogBehavior::afterError]  [26]
  Updating search indexes (attempt: 1) - Error (time: 0.000s): Class
  'barrelstrength\sproutforms\elements\Entry' not found

I had installed Sprout Forms and also Sprout Email recently, but then disabled & removed them when they weren't quite what I was after. However, I see they've left some pieces of themselves in my database: tables sprout_addresses, sproutemail_notificationemails, sproutemail_sentemail, sproutimport_seeds, sproutreports_datasources, sproutreports_reportgroups, sproutreports_reports. (I had also installed Sprout Import on this site back when it was still running Craft 2 but it's long gone now, or I thought it was.)

Can I just drop these tables? And does that solve my queue problem? I'm tempted of course to just try and see, but don't know where there may be more bits of these plugins in my database or codebase that might cause trouble if I disappeared these tables. For example, I do see a FK relationship from the one existing row in sproutemail_notificationemails to a row in craft_elements; not sure what happens if I delete that row too.

Would be grateful for advice on the best approach here. Thanks in advance.

UPDATE: This should no longer be an issue. All of our plugins have been reviewed and updated with more consistent uninstall behavior.

If you no longer have those plugins installed, you should be able to drop all of those tables without creating any new issues.

That may not clean up all of your data though, as the queue error is pointing to an orphaned Element. To see any orphaned elements you can run a query search for all Sprout elements on your elements table. The following may need to be adjusted if you have a different database prefix:

SELECT *
FROM craft_elements
WHERE type LIKE '%barrelstrength%';

Deleting these Elements from your elements table should cascade and clean them up anywhere else they may be used in the database. Be careful with the following operations and be sure to test on a dev database to make sure everything works as you expect. There could be scenarios I'm not considering.

Once you find the Elements you want to delete update your query to just grab the Element IDs of the specific Elements you want. You could also query these ID values from the plugin-specific element tables if they are still in your database.

SELECT id
FROM craft_elements
WHERE type LIKE '%barrelstrength%'

To delete Elements you're going to pass those IDs to a delete statement. A standalone delete query will look something like this:

DELETE FROM craft_elements
WHERE id IN (1, 2, 3);

If you want to combine both queries since you're selecting the IDs from the same table that you are deleting from you can create a temp table to get around that. This can result in a slow query if you have a large number of elements. In that case, you could delete multiple batches of a smaller number of elements.

DELETE FROM craft_elements
WHERE id IN (
    SELECT tempElements.id
    FROM (
        SELECT id
        FROM craft_elements
        WHERE type LIKE '%barrelstrength%'
    ) tempElements
);

Again, please be careful when operating on the Craft database directly. Be sure to create backups, test on a development database, and review things closely. Craft has a highly relational data structure and plugins may behave in different ways in how they store their own data.

A less risky way of approaching this may be to write a short script and delete the Elements using the Element API:

foreach ($elementIdsToDelete as $elementId) {
  Craft::$app->elements->deleteElementById($elementId);
}


Plugin that lets user select focal point/cropped area I would like to let the editor of a specific entry select the focal point and cropped area each time she selects an asset for an asset field.

How can I achieve that?

I know about the built in focal point function in Craft CMS 3 that lets me edit one asset and set a focal point - but what I want is:

Let the user select focal point each time an asset is selected
If the asset field has a fixed aspect ratio, let the user select specifically which portion of the image should become the cropped version.

Like this:

I found a plugin called Ansel, which seems to let me do what I want. My question is if there is another way - or built in way to achieve what I want?

With Craft CMS 3, focal points are built into the Image Editor.

  To launch the Image Editor, double-click on an image (either on the Assets page or from an Assets field) and click on the “Edit” button in the top-right of the image preview area in the HUD. Alternatively, you can select an asset on the Assets page and then choose “Edit image” from the task menu (gear icon).

more info

Here's how you could use the asset's focal point in your code:

Check if image has a user-defined focal point:
{% if image.hasFocalPoint %}

Get the focal point values:
{{ image.focalPoint.x }} / {{ image.focalPoint.y }}

Get the focal point values as CSS (e.g. for use in the object-position value):
{{ image.getFocalPoint(asCss=true) }}

I think in Craft CMS 2, these two plugins were widely used:

Focal Point Field
Focus Point


Can't update past 3.0.15 Here's what I'm getting:

Error: An error occurred

Output: Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Installation request for craftcms/cms 3.0.18 -> satisfiable by craftcms/cms[3.0.18].
    - craftcms/cms 3.0.18 requires enshrined/svg-sanitize ~0.9.0 -> satisfiable by enshrined/svg-sanitize[0.9.0] but these conflict with your requirements or minimum-stability.
  Problem 2
    - craftcms/cms 3.0.18 requires enshrined/svg-sanitize ~0.9.0 -> satisfiable by enshrined/svg-sanitize[0.9.0] but these conflict with your requirements or minimum-stability.
    - pierrestoffe/craft-language-redirector 1.0.2 requires craftcms/cms ^3.0.0-RC1 -> satisfiable by craftcms/cms[3.0.18].
    - Installation request for pierrestoffe/craft-language-redirector 1.0.2 -> satisfiable by pierrestoffe/craft-language-redirector[1.0.2].

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

I've attempted:

removing vendors directory
removing composer.lock file
updating via CLI
changing craftcms to 3.0.18 and running install

Anything else I can try?

I had a similar issue - update your composer.json file as per this question:

Composer was unable to install the updates

Alot of additional things may have got added to your composer.json file.


Do I need 2 licenses for staging and production Or is one pro license enough? We're running a stage environment and a production environment for the same website. Thoughts?

One is enough you don't need a license for a development server at all source

And here is something from FAQ as well link

  Is there a way I can try Craft Client or Pro out before buying?
  Yes. As long as you’re running Craft CMS from a non-public-looking domain name (e.g. “mysite.dev” or “staging.mysite.com”), you will have the option to test the Client and Pro editions indefinitely.

And a info from the Terms and Conditions

  3. License Agreement Model
  This is a single-installation license, meaning you may integrate a Licensed Copy into one public-facing (“Internet”) or internal (“intranet”) web root directory at a time (the “Website”). You may also install and use Craft without limitation for local development and testing purposes.


Re-directing to front-end after login I have created an entry that requires users to be logged into to see it. This was just a minor request from our client and we didn't want to spend a lot of time setting up login forms etc.

Therefore I have just added {% requireLogin %} to the top of the entry's Twig file. This works great, so far so good.

The problem comes however when a user visits the URL for that page:

www.foo.com/lorem

They are re-directed to the Craft login, as expected, but once they successfully login, instead of being re-directed back to the page, they are instead taken to the Craft admin dashboard, with the pages' slug at the end. So:

www.foo.com/admin/lorem

Can anyone shed some light as to what is going on here? How can I make it so once users are loged in, they are re-directed back to the page? I've seen Craft has a postLoginRedirect config, but I'm guessing this can't be set on a per-page basis.

As far as I understand it, the postLoginRedirect only affects login forms defined on the the front-end. If a user visits the login page (through a 'login' link for example), then they will be redirected to 'postLoginRedirect' after logging in. They will also be redirected there if they attempt to visit the login form directly when already logged in.

Your best option is to just create a quick login page template, like the one provided in the docs. Craft will automatically look for 'login.html' in your templates folder - otherwise you can specify the location using the loginPath config setting.

With that defined, if a user tries to visit any page that has {{ loginRequired }} specified, they will automatically get redirected to the login page and subsequently be redirected back to the original page request after login.


Is it possible to image upload on a particular size using a control panel? I am using the commerce plugin. I want to display an image of the specific size without CSS is there any specific way in the commerce plugin?

Yes, you can use image transform option for that.
You should go to control panel and go to below path
Settings > Assets > Image Transforms
Then create new image transform.
Using it, you can control height, width, image quality, image format and other things as well.


Multisite, second language Live Preview not working I have an English site - https://dev.mysite.com and a Japanese site - https://dev.mysite.com/jp.

Live preview works great for the English site, but the Japanese site has the following error:

Mixed Content: The page at 'https://dev.mysite.com/admin/entries/home/3-home?site=japanese&draftId=90' was loaded over HTTPS, but requested an insecure resource 'http://dev.mysite.com/jp?x-craft-live-preview=dbSSGfPfBY&token=LTNsMdKk-I8XWFyoh7ozK2akf4Hy_oOO'. This request has been blocked; the content must be served over HTTPS.

I have the Base URL set within the Sites admin panel to https, as well as the siteUrl within general.php.

What am I missing?

Thank you!
Kelly

Issue within the .htaccess file!

These lines were causing the redirect to https to malfunction:

# Remove trailing slashes
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [R=301,L]


Re-using entry types across multiple sections Is there way to a create an entry type that you can re-use on different sections?

Essentially what I would like to do is define one entry type, such as a "Product" entry type, and add fields for a product. Then I'd assign this "Product" entry type to each section, as required.

This would prevent me from having to create a "Product" entry type on every section and add the same fields to each one.

Entry Types are unique to their Sections. You can't have one Entry type shared between multiple Sections. You can however use Field Groups to set your Field Layouts for each Entry Type. This will remove the need to add each and every field individually to each Entry Type.

More info on Field Layouts can be found on the docs.


Custom field plugin: Unable to find template / General custom field plugin information I am still relatively new to Craft CMS.
I am trying to make a custom field plugin for Craft 3 but I am struggling to understand why I can't render my form template.
The fieldtype should render a map with markers in an entry, depending on which checkbox is clicked before map creation.
I have the following code in my Field.php file:
public function getInputHtml($value, ElementInterface $element = null): string
{
...

Craft::$app->getView()->setTemplateMode(View::TEMPLATE_MODE_SITE);
$input = Craft::$app->getView()->renderTemplate('locations-map/_includes/forms/mapElement', $variables);
}

And I get the following error:

This is the result from all the vague(in my opinion) information in the internet about making custom field types in Craft 3 CMS.
If you have an idea how to access this template or just any information about custom fields, please feel free to share. (Yes, I have read the official documentation)

Where are you storing your mapElement template? - Unless it is stored in the same folder as the templates for the front end of your site, then

Craft::$app->getView()->setTemplateMode(View::TEMPLATE_MODE_SITE);

is telling craft to look in the wrong place.

If you've got it stored in your plugin directory, then you don't need to change the template mode at all, as per : https://docs.craftcms.com/v3/extend/updating-plugins.html#rendering-templates


Guest Entries - Two ajax forms for different section entries. Receiving 404 only on second form? I am using the guestentries plugin to create two different section entries. I have two similar html forms on the same front end page. They both use the jquery validate plugin before submiting via ajax. The first form for sectionId(3) does some stripe token generation before submitting to the plugin to submit the payment and create the entry. This is working fine.

The second form doesn't do any stripe calls and is using very much the same jquery ajax call to submit to a sectionId(4). This ajax submission is always returning a 404 and doesn't get to the guestEntries plugin so it seems craft isn't handling this submission like it should?

Succesful request/response

[Code]

    var formData = $("form[name='playerForm']").serialize();
    $.post('/', formData , function(response) {
      if (response.success) {
      //On Submit Success
      $("form[name='playerForm'] input[type='text'],select").val("");

      $('#playerForm').slideUp();

      $('#registered_user_name').text(response.title);
      $('#myModal').modal('show');
      $('#submitLoader').replaceWith('<input type="submit" class="submit" id="playerSubmit" value="Continue" />');

    }else{
      console.log(response);
    }
  });

[Form Data]

CRAFT_CSRF_TOKEN:kv8AfC8Odbhq7OFX6eUhJEi~lm2LqTgmubFer48b|4af89cb67bc43b2efb63a00273e638708f85f5ab
action:guestEntries/saveEntry
sectionId:3
fields[firstName]:Test
fields[lastName]:Guy
fields[homeTown]:Town
fields[phoneNumber]:234 342 2343
fields[companyEducationalInstitution]:Test Company
fields[averageScore]:81-90
fields[yearsInTheTournament]:1
token:tok_19pQkWKdnBUCmelLfVYMRhaF
fields[email]:test@test.com

Failed request/response

[Code]

var data = $("form[name='sponsorForm']").serialize();

$.post('/', data, function (response) {
  if (response && response.success) {
    console.log(response);
  } else {
    console.log(response);
  }
  $('#submitLoader').replaceWith('<input type="submit" class="submit" id="sponsorSubmit" value="Submit" />');
});

[Form Data]

CRAFT_CSRF_TOKEN:kv8AfC8Odbhq7OFX6eUhJEi~lm2LqTgmubFer48b|4af89cb67bc43b2efb63a00273e638708f85f5ab
action:guestEntries/saveEntry
sectionId:4
fields[sponsorFirstName]:Test
fields[sponsorLastName]:Guy
fields[sponsorPhoneNumber]:252 356 5626
fields[company]:Test Company

I've compared the request headers and they are identical so I don't think it's an ajax header problem. Not sure why first form would work and second would fail. Any help is greatly appreciated.

I shall answer my own question.

The issue was because I was logged in as admin in another browser tab. I was not receiving the "Unauthorized" response from craft. Just the 404. By testing in an incognito window I was able to see I was receiving an unauthorized response from craft which led me to the problem. Which was the sectionId for that particular form was incorrect. SectionId on second form should have been 2 not 4.

Hope this helps anyone else having a similar problem.


Redactor II Craft 2.5 Prevent Paragraphs I realize Craft 2.5 ships with Redactor II which has many changes.

With Redactor I a combination of

paragraphize: false,
replaceDivs: false,
linebreaks: true,
enterKey: false

kept text from being wrapped in p tags.

I want to give someone the ability to add simple formatting such as bold and italic, but not wrap it in any HTML.

Has anyone found how to continue doing this with Redactor II?

Thanks.

I just found the following in the updated docs for the enterKey setting:

  enterKey — This setting allows to prevent use of Return key.
  With this set to 'false' and pastePlainText is set to true, line breaks will be replaced by spaces.

So make sure you are on Craft 2.5.2757, as it includes Redactor II 1.2 which has got the new paste settings and try this Redactor config:

"enterKey": false,
"pastePlainText": true,

Redactor II deprecated the paragraphize setting, but as noted in the comments, it's easy to remove HTML tags with the striptags filter:

{{ asset.caption|striptags('<em><strong>')|raw }}

Every tag listed in the param string is whitelisted and won't get removed.


How do I output only country part of location field using the SimpleMap plugin? The docs of the SimpleMap plugin mention it's possible to output only part of the full location, e.g. just the country by using

{{ myMapField.country_short }}

but in my project I get this error when I try doing so:

Internal Server Error

Craft\SimpleMap_MapModel and its behaviors do not have a method or closure named "country".

Same result without the _short suffix.
The plugin is set up properly as I can correctly output full address, lat, lng, zoom values like so:

{{ myMapField.address }}
{{ myMapField.lat }}
{{ myMapField.lng }}

Just splitting up the full address results in the above error. What's going wrong?

Never used the plugin, but from the docs:

parts
This contains the locations address, broken down into its constituent parts. All values are optional so you'll need to have checks on any you use to make sure they exist.
A list of the available values can be found here.
To access the short version of any part, append _short to the end of its name. E.g. {{ myMapField.country_short }}.

Sounds like the country info is optional and may not exist on the model, hence the note to check if it exists or not first.
i.e.
{% if myMapField.country_short is defined %}
    {{ myMapField.country_short }}
{% endif %}


`Invalid argument supplied for foreach()` error We've made a local copy of a site that is working fine in a staging environment but locally is getting the following error:

`Invalid argument supplied for foreach()`

Seemingly coming from craft/app/fieldtypes/BaseOptionsFieldtype.

Does anybody have any thoughts on what is causing this and how to resolve? Is happening both in the front-end and the admin area.

Looking at the code where your errors is occurring (line 46 of craft/app/fieldtypes/BaseOptionsFieldType.php), it looks like you have either a Checkboxes or Multi-Select field whose options setting is somehow set, but not set to an array. Not sure how it could have gotten into that state, but that’s the only thing that would explain your error.

Try re-saving any Checkboxes/Multi-Select fields (or if you have any 3rd party field types installed that might be extending Craft’s BaseOptionsFieldType, that would be even more likely the culprit), ensuring they have at least one option set.


Trigger Task Status Icon I have a plugin that starts a task and subtasks from a CP widget AJAX call. The tasks are running without a hitch, but for some reason on production, the icon does not appear when the tasks start running unless I refresh the page.

On my local dev site (MAMP), the task icon appears as soon as the code below is called.

I am using this code to start the pending tasks I created:

Craft.cp.runPendingTasks();

Any ideas? Is there a different JS command I should be using?

I use this to force the task icon to show up immediately:

Craft.cp.setRunningTaskInfo({
    "id": "task ID",
    "level": "0",
    "description": "description",
    "status": "running",
    "progress": 0
});
Craft.cp.trackTaskProgress();