Commerce: How do I use an adjustor for line items?

I'm finding the question hard to follow, but if I am understanding you, then yes I would do it all in the adjuster - rather than using a discount here... I don't see what using a Commerce discount here offers, as you can't really express your credits system in any way meaningful that relates to a Commerce discount I think.

So this indeed looks like a job for an adjuster, which can act at either the lineItem or order level as per the linked example.

In terms of where you put that adjuster, there are basically three steps.  The first two are in your main plugin file:

public function init()
{
  Craft::import('plugins.yourPluginHandle.adjusters.YourAdjusterClassName');
}

and then later in that file...

 public function commerce_registerOrderAdjusters(){
   return [
     new BusinessLogic_TaxRemover
   ];
 }

Then, you have the actual code in your adjuster to do whatever you want to do, which (repeating that example), looks like this:

    <?php

    namespace Craft;
    use Craft\Commerce_LineItemModel;
    use Craft\Commerce_OrderAdjustmentModel;
    use Craft\Commerce_OrderModel;

    class BusinessLogic_TaxRemover implements Commerce_AdjusterInterface {

    public function adjust(Commerce_OrderModel &$order, array $lineItems = []){

    $myAdjuster = new Commerce_OrderAdjustmentModel();

    $order->baseDiscount = $order->baseDiscount - 5;

    $myAdjuster->type = "Test";
    $myAdjuster->name = "Test Adjuster";
    $myAdjuster->description = "Takes $5 off the order";
    $myAdjuster->amount = -5.0;
    $myAdjuster->orderId = $order->id;
    //if your Adjuster affects lineItems rather than the total, you record the ids here
    $myAdjuster->optionsJson = ['lineItemsAffected'=>null];
    $myAdjuster->included = false;

    return [$myAdjuster];

   }

}

...the main thing to note in there is you need to record the ids of any lineitems you're adjusting by changing this - ($myAdjuster->optionsJson = ['lineItemsAffected'=>null];


Plugin init function executed more than once

The init function should only trigger once for each instance. So when you do something like new Plugin it is executed multiple times.

But keep in mind that it is executed in every request. So when you are in the CP there are many different ajax calls (every time when you reload entries at the index page for example). You'll create a new row for each of those requests

In order to disable your function you can check

$request = Craft::$app->getRequest();
if (!$request->getIsAjax() && !$request->getIsConsoleRequest()) {

}


Craft Commerce - empty cart.adjustments data

Sounds like you have not submitted a shipping method selection to the cart.


Edit custom field value inside "commerce_orders.onBeforeSaveOrder" event

That looks right, but I think you may need to set the value of that field to '1' - looking in the craft_content table, it seems switches are stored as 0 and 1.

      $order = $event->params["order"];
      $order->setContentFromPost(array(
          'ediCheck' => 1,
      ));

If that still doesn't work, try throwing in a craft()->commerce_orders->saveOrder($order); at the end of your function.  It shouldn't be needed though as it should fall through to the saveOrder it's going to do anyway....


Front End Entry Form - File/asset field not saving when ajax submitted

Finally found the answer after much time spent on it.
The $(this).serialize() loses the file input - and can't submit.
Updated ajax submit to
$.ajax({
    type: 'POST',
    url: url,
    data: new FormData(this) ,
    dataType : 'json', // changing data type to json
    processData: false,
    contentType: false,
    success: function (response) { // here I'm adding data as a parameter which stores the response
        console.log(response); // instead of alert I'm changing this to console.log which logs all the response in console.
    }
});


As Victor rightfully points out, the {% paginate %} tags require an ElementCriteriaModel, so you can't do what you're doing in your first example because as soon as you call:

{% for databyte in allDatabytes %}

Craft hits the database and converts the ElementCriteriaModel into actual EntryModels.

We also don't have support, yet, for passing :empty: into things like AssetFields, TagFields, etc., which is why your second example won't work...  however that is on our list to add!

In this case, I think your best bet is going to be to do through the search service with something like this:

{# Search for 10 entries in the 'databytes' section where the 'series' assetField doesn't have anything selected. #}
{% set myCriteria = craft.entries.section('databytes').search('-series:*').limit(10) %}

{% paginate myCriteria as entries %}
    {% for entry in entries %}
        {{ entry.title }}
    {% endfor %}

    {% if paginate.prevUrl %}
        Previous Page
    {% endif %}

    {% if paginate.nextUrl %}
        Next Page
    {% endif %}
{% endpaginate %}


How to implement mailchimp plugin to target different mailists?

If the plugin in question is my MailChimp Subscribe plugin, you can easily target different lists by adding a hidden field called lid to your form with your list ID:

<input type="hidden" name="lid" value="2fd6ec09cf">

This will override the config setting (see the examples under configuration in the repo for more information on this).


Validation errors will still get logged to craft/storage/runtime/logs with a [warning] label.

Other than that, you options are just like you'd debug anything else in PHP.  Preferably with xDebug, but you can always manually Craft::log() and read the log files, too.


How can I filter which children I want to show in a sub navigation menu

The way I usually accomplish this is to add a "Hide From Nav" Lightswitch field to the sections I want to filter.

This will filter out any entries where the Lightswitch is "on".

{% set subnav = craft.entries.descendantOf(mainEntry).hideFromNav('not 1').level(2) %}


Enupal Snapshot plugin on local windows environment - can't save path

Have emailed Enupal support based on comment suggestion.


Does Craft CMS have skeletons/starter/boilerplate templates?

Here's an example of how you can do it with Craft 3 and composer create-project: nystudio107/craft

This is discussed in the Setting up a New Craft CMS 3 Project article.


Using the coupon code from Craft Commerce site

I had this problem and the cause was that I was doing this in the base template:

{% set cart = craft.commerce.carts.cart %}

When I should be doing the following:

{% if cart is not defined %}
    {% set cart = craft.commerce.carts.cart %}
{% endif %}

The reason behind is that the cart object in cart.getError function was always being initialized instead of getting the cart from the POST response.


You can assign a user to certain groups via

Craft::$app->getUsers()->assignUserToGroups($user->id, [1,2,3]);

Would assign them to the groups with the ids 1, 2 and 3


How to get rendered image paths from the ElementAPI?

Rather than calling getRawContent(), just explicitly cast your Rich Text field data into a string:

'summary' => ($entry->summary ? (string) $entry->summary : false),


How to extract static messages from templates into translation files?

Update:

For Craft 3, we use the Yii 2 Inspections plugin for PhpStorm to do this now. https://plugins.jetbrains.com/plugin/9400-yii2-inspections

There is a translation inspection that will let you know which strings are missing translations and which translations are no longer in use.

Old:

We currently have our own command line tool that goes through all of Craft's files and extracts anything in Craft::t() (for PHP), and |t (for Twig) and Craft.t() for JavaScript.

What we would probably do is make that tool into a yiic command and update it to let plugins take advantage of it for their own files as well.

Will add it to the list.


Freeform AJAX submission not working when two forms are on same page

Im running into the same issue. In my case they are completely different forms but both with "Enable AJAX" set to true. Could not find anything in the docs either.

This is the error I am seeing. I think I have it narrowed down to the honey pot field not being unique per form. Removing the honey pot setting, fixes the issue.

[DOM] Found 2 elements with non-unique id #freeform_form_handle:


Trouble with Custom Command in Custom Plugin. How do I do it?

You should see your commands when using the Craft CLI.
First thing to check would be that the module is registered in app.php, both in the modules and bootstrap arrays. Craft's documentation on that is here.
I find the best way to quickly validate that your module is registered, is by dumping something out from the module init() function. Craft::dd('Registered') does the trick. If you don't see anything on the frontend, your module isn't getting loaded into Craft.
Secondly, I would check that you are correctly setting the controllerNamespace, so that Craft knows where to look for controllers, depending on your request. Their documentation on that is here.
Finally, check that you have some valid functions setup in your controllers. Each function name should be prefixed with action. For example: actionRun() in a JobController.php file will be run with php craft mymodule/job/run.


Entries field: Output entries related to category

The targetElement and sourceElement take either an ID, an Element Model, or an array of either.

So, in your example, you'd want to do:

{# Categories #}
{% set CatToDo = craft.categories.slug('things-to-do').first %}
{% set CatToEat = craft.categories.slug('things-to-eat').first %}

{% set toEat = craft.entries.section('yourSection').relatedTo({
   targetElement: CatToEat,
   field: 'activityPicker'
}) %}

[...]

Notice the .first in there as the difference. You will only want the one category since you're passing the slug.

Note: This assumes that CatToEat is indeed the targetElement. See here for more information: http://buildwithcraft.com/docs/relations#the-relatedTo-param


When image transforming png to jpg, alpha layer become lined

You'll need to have Imagick installed on your box if you want to preserve alpha channels in a PNG during transforms.

If Craft sees it is installed, it will use it by default.


How do I import database using the CMS Craft 3

For syncing your database in Craft 3 you can use the Project Config please read the instructions in the link how to use it and what it does

  Once that’s enabled, Craft will start storing the project config in a config/project.yaml file. Any time something changes that is managed by the project config, that file will get updated to match. And any time Craft detects that project.yaml has been updated on its own (e.g. if it was changed in a Git commit that was recently pulled down), any changes in it will be propagated to the local Craft install.

So store the file in your directory and Craft will do the rest


Getting Craft's storage folder to work on Heroku

For anyone else trying this: the solution I eventually came up for was to follow these instructions for adding an argument to the Procfile to tell Heroku to tail Craft's log file into the "Logplex" stream.

There might well be situations where Brad's suggestion (using a plugin to write the logs to stderr) is preferable, but I wasn't sure what the implications would be for logs in development (where it's fine for them to be written to the file system). Adding an argument to the Procfile side-steps this issue, since it's only run by Heroku.

My Procfile now looks like this:

web: vendor/bin/heroku-php-nginx -C nginx_app.conf -l storage/logs/web.log web


How can I display related entries selected within a Matrix field?

When you relate an element from a Matrix block, it's important to know that the relation is between the Matrix block and the related element; nor the entry (or whatever has the Matrix field) and the related element.

So, the correct way to select related elements through a Matrix field is:

{% set employer = craft.entries.section('companies').slug(segment) %}
{% set personnel = craft.entries.section('people').relatedTo({
    targetElement: employer,
    field: "matrixField.relationField"
}) %}

Update: Added a missing } on the last line.


I guess you would need to have your own method in your controller to fire up the indexing tool. From what it looks like, you need a few things to get going:

The classname of the tool i.e AssetIndex
An array of asset sources or * for them all
An indexing session id
An array of parameters to send to the tool

So I managed to get something working with the following code (this would go in your plugin controller)

public function actionUpdateIndex()
{
  // Get the AssetIndex tool
  $tool = craft()->components->getComponentByTypeAndClass(ComponentType::Tool, 'AssetIndex');

  // Generate an AssetIndex session id for us to use
  $sessionId = craft()->assetIndexing->getIndexingSessionId();

  // Set up some params
  $params = array(
    'start' => '1', // Tells the tool this is the initial request
    'sources' => '*', // All of them or [1,2,3] just ids1
  );

  // Get an initial response from the tool, will contain an array containing the assets to index
  $response = $tool->performAction($params);

  // See [1]
  foreach($response['batches'] as $key => $value)
  {
    foreach($value as $key => $batch)
    {
       // All the needed params are set in the array to do the index
       $tool->performAction($batch['params']);
    }
  }

}

Each time you call $tool->performAction($batch['params']); you will an array back, something like:

Array
(
 [success] => 1
)

[1] Because this is the initial request craft will return an array with a batches index, which we then have to do a few loops through, it looks something like this:

Array
(
 [batches] => Array
  (
   [0] => Array
    (
     [0] => Array
      (
       [params] => Array
        (
         [sessionId] => 6d08c5ba-169f-4b99-a7bd-cdc26c9428c7
         [sourceId] => 1
         [total] => 12
         [offset] => 0
         [process] => 1
        )

       )

      )

    )

 [total] => 0
)

Not sure if this is the absolute best way to do it, I was learning as I was going, but this worked for me so hopefully it'll work for you too :)


It shouldn't be that slow to bootstrap, but even if you're not doing anything with the plugins in your template, they are still loaded and instantiated with every request.

If I were you, I'd do some profiling with Blackfire or NewRelic to see what's really going on.


Can Craft's Rich Text fields be configured to use Redactor's autosave?

I'm just thinking about what would need to happen in order for this to work.

Craft would have to expose Redactor's autosave configuration somehow - either via UI or a Redactor config file.
You'd have to write a plugin and point the autosave configuration to an action on a controller in your plugin.
That action would be responsible for persisting the RTE content as well as the entry and field it came from (since you can have multiple RTEs on a page) - likely the database.

All-in-all, not a very robust solution. It'd be much more likely that we implemented our own autosave solution that worked for all fields at the entry level, instead of just the RTE.


Only executing if a matrix checkbox has a specific value

{% if block.checkboxFieldHandle.contains('someChkbxValue') %}

Executed!

{% endif %}

actual for Craft v2.x and v3.x


Can you insert Craft variables into SCSS files and have a plugin generate CSS?

I did the port of AutoMin to Craft, and I don't think what you want to do is possible with it. Maybe if you were somehow able to write a new file to disk, with the variables defined in it, and then feed that into the AutoMin, it could work. But seems like a pretty complicated solution.

I'm not sure exactly what you're trying to achieve, but in previous projects where I've let the user control colors and fonts on certain objects, I've just done it with pure CSS. If I wanted to let the client define the link color, I'd just do something like this in :

<style type="text/css">
    a { color: {{ myGlobal.linkColor }} }
</style>

And then not define the link color in my stylesheet.

But this is maybe too simplistic for what you're trying to do? :)


Here's how you can pass in the CSRF token via JavaScript: http://buildwithcraft.com/help/csrf-protection#updating-your-javascript


A multi-environment config needs to have a * key. This might work:

return array(
  '*' => array(),
  'craft.dev' => array(
    'siteUrl' => array(
      'de' => 'http://craft.dev/',
       en' => 'http://craft.dev/en/',
    ),
  ),
);


Trouble calling service methods from primary module class

Where do you instantiate your orders component?

As long as you're calling the setComponents early in your init method as follow, you should be able to access it anywhere in your plugin class:

...
parent::init();
self::$plugin = $this;
$this->setComponents([
        'orders' => OrdersService::class,
]);
...


Wrap embeds with HTML in rich text field

I suggest a Twig filter so you can do something like this in the template:

{{ entry.body | wrapembeds }}

This is something to love about Craft - the ease of building Twig filters.

In the plugins directory create a folder videoembeds.

Create the main plugin file WrapEmbedsPlugin.php:

<?php
namespace Craft;

class WrapEmbedsPlugin extends BasePlugin
{
    public function getName()
    {
        return Craft::t('Embed Wrapper Twig Filter');
    }

    public function getVersion()
    {
        return '0.0';
    }

    public function getDeveloper()
    {
        return 'Your Name';
    }

    public function getDeveloperUrl()
    {
        return 'http://yoursite.com';
    }

    public function hookAddTwigExtension()
    {
        Craft::import('plugins.wrapembeds.WrapEmbedsTwigExtension');
        return new WrapEmbedsTwigExtension();
    }
}

Create another file WrapEmbedsTwigExtension.php:

<?php
namespace Craft;

class WrapEmbedsTwigExtension extends \Twig_Extension
{
  protected $env;

  public function getName()
  {
    return 'WrapEmbeds Twig Extension';
  }

  public function getFilters()
  {
    return array('wrapembeds' => new \Twig_Filter_Method($this, 'wrapembeds'));
  }

  public function initRuntime(\Twig_Environment $env)
  {
    $this->env = $env;
  }

  public function wrapembeds($content)
  {
    $filtered = preg_replace_callback('//', function($matches) {
      return '
'. $matches[0] . '
';
    }, $content);

    $charset = craft()->templates->getTwig()->getCharset();
    $filtered = new RichTextData($filtered, $charset);

    return $filtered;
  }

}

Enable the plugin in the admin then add the filter to the template tag. Hopefully this is enough to get you started adding custom Twig filters. Simple once you know how and very handy!


You can change the default entry status in your section settings.

Example: If I would set the German toggle to disabled, all entries added to German local will be disabled by default.


"Sites" in Craft 3 replaces the old "Locales" concept in Craft 2.

There's not much documentation on them yet, but the setup process is virtually the same as it is in Craft 2 for locales.  The main difference is that a "site" isn't necessarily tied to a language code, like it is in Craft 2.

https://craftcms.com/news/craft-3-multi-site

  Update: Localization docs for Craft 3


It’s not possible for a form to simultaneously invoke two controller actions.

You would need to write a plugin that provides its own controller, which in turn could be used to invoke the other controller actions.

class MyPluginController
{
    public function actionSaveEntryAndSendNotification()
    {
        // Save the entry
        craft()->runController('guestEntries/saveEntry');

        // Send the notification
        craft()->runController('formNotification/getForm');
    }
}

If "FormNotificationController" is already your own custom plugin, then it might make more sense to just call craft()->runController('guestEntries/saveEntry'); from the top of actionGetForm(). Or just save the entry yourself from the controller action – the Guest Entries plugin is really pretty simple; most of the heavy lifting is provided by the EntriesService - saveEntry() API.


Sprout forms AJAX submission giving Template not found

If you're using template overrides, could you please make sure that the next line is in the <form> ... <\form> tag?

{% hook 'sproutForms.modifyForm' %}

This line is required in Sprout Forms for Craft3 if you have the spam protection enabled in the plugin settings.


Dynamically load craft entries based on twig variable

You can't use Twig for dynamic interactions on your site, as it is a server side language. Twig compiles to PHP code, which is then rendered and loaded to the DOM.

What you'd need is a script running in userland. The technique Stehen suggested is one way to do it, but you probably don't want your site's visitors to load all data right from the start, using the button simply to reveal already loaded "extra entries".

I'd say you should learn how to do AJAX loading with Javascript or jQuery. This is how you could properly address the desired behavior.

A way to make it work with your Craft template would be to split your entries list into multiple parts using the paginate tag. The first block would load right away and then with every click on that button each succeeding entry block is loaded into the DOM via Javascript.


Your issue is probably that you're actually comparing an EntryModel (entry) to an ElementCriteriaModel (the array-like object used for querying entries, which is returned by the craft.entries call).

Something like this should do it:

{% if entry.section.handle == 'homepage' %}
    {{ entry.hero }}
{% elseif entry.section.handle == 'smallgroups' %}
    Groups
{% else %}
    {{ entry.title }}
{% endif %}

Assuming your section handles are correct, the above should work – although this is a perfect use for using the {% switch %} tag instead of {% if %}, which in my opinion would make your code more readable:

{% switch entry.section.handle %}
    {% case 'homepage' %}
        {{ entry.hero }}
    {% case 'smallgroups' %}
        Groups
    {% default %}
        {{ entry.title }}
{% endswitch %}


The craft.categories tag returns an ElementCriteriaModel, so parentCategory.title really shouldn't work. Try changing the first line of code to:

{% set parentCategory = craft.categories.slug(craft.request.getSegment(2)).first() %}


How to make URLs translatable in Craft 3

To give this an answer, the URI can be set on a per-site basis, so it is simply a matter of setting the URI for the English site to about-us and the URI for the Dutch site to over-ons on the section's settings page.


I solved it.

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


You can try the following code

{% set ratingsSum = 0 %}
{% for order in pastOrders %}
    {% set ratingsSum = ratingsSum + order.orderDeliveryTime.value %}
{% endfor %}

{% set ratingAverage = ratingsSum / pastOrders | length %}
AverageTime:{{ratingAverage}}

Difference between yours and my code is i have added .value with order.orderDeliveryTime


In plugin combine a returned entry with custom table data

Just have your plugin supply a custom MyPluginEntryModel that extends Craft's EntryModel and merges in any custom attribute definitions from your custom table.

class MyPluginEntryModel extends EntryModel
{
   ....

    protected function defineAttributes()
    {
        return array_merge(parent::defineAttributes(), array(
            'customAttribute1' => AttributeType::Number,
            'customAttribute2' => AttributeType::String,
        ));
    }

   ....
}


Is there a way to manually trigger an asset transform before calling getUrl()?

You could use my Preparse Field plugin to generate transforms when an entry (or any other element) is saved.

Create a preparse field and create some twig that makes the same transforms that you do in your template. Don't care about the output, the only thing you want it to do is generate the images on save. Assuming you attach the field to an entry, and you have a field named myImageField, the code could look something like this:

{% if entry.myImageField | length %}
  {% for image in entry.myImageField %}
    {{ image.getUrl({ width: 1600 })
    {{ image.getUrl({ width: 1200 })
    {{ image.getUrl({ width: 800 })
    {{ image.getUrl({ width: 400 })
  {% endfor %}
{% endif %}

When you save the entry, this code will run, and create any new image transforms. When the entry is displayed in the front-end, the image transforms will already have been created.

Beware that this will not actually increase the speed of the transforms, only shift the time it takes from the front-end user over to the admin. But I find that this is more acceptable in most of my use-cases.


The relatedTo parameter accepts an element, the ID of an element, an array if element ids or an object of type EntryQuery.

All you need to do is to pass the ID rather than the title

targetElement: entry.id

Furthermore if you use Craft 3 you might want to execute your query by calling .all()
talents doesn't contain an array. It contains an object of type EntryQuery that can be executed in order to get an array of elements


How can I automatically generate responsive images from a single hi-res asset?

You can do this using image transforms.

There are a couple things you’re going to need to consider though:

Not every image will necessarily be high-res (e.g. a computer screenshot taken on a non-retina screen)
You probably don’t want to output images that are larger than their original size

For #1, we need some way of identifying images that are 1X vs. 2X. You could do this a couple different ways:

Give your assets a Lightswitch field that identifies if it’s a 2X image
Use a consistent naming convention for 2X image filenames, e.g. “filename@2x.ext” (to borrow Retina.js’s convention)

I personally prefer the second. (That’s what we do on buildwithcraft.com, except we use “.2x” instead of “@2x”.)

We can tackle #2 with some logic in the template that only uses a transform when the resulting size is going to be smaller than the original image.

It’s the combination of these two problems where things get interesting: You need to figure out the image’s CSS pixel size (based on whether it’s 1X or 2X) before you start determining whether it needs a transform, and how big to make the transform, etc.

Here’s what we came up with for Craft’s documentation (such as the image on the asset transforms page):

Create a macro called srcset() which will be responsible for outputting a <source> or <img> tag’s srcset= attribute and value, and optionally the width= and height= attributes as well. It should accept the following arguments:

image - an AssetFileModel
maxCssWidth - the maximum “CSS pixel” width that we want to output the image at
includeDimensions - whether the macro should also output the width= and height= attributes.

Create a <picture> element with nested <source> and <img> elements per the Picture spec, using our new srcset() macro to write out the srcset= attributes.

Here’s what the macro looks like:

{% macro srcset(image, maxCssWidth, includeDimensions) %}
    {%- spaceless %}
        {# Is this a 2X image? #}
        {% set is2x = image.filename matches '/@2x\\.\\w+$/' %}

        {# Determine the CSS width for the image, if it were output at 100% #}
        {% set cssWidth = (is2x ? round(image.width / 2) : image.width) %}

        {# Determine the image size that 1X screens should get #}
        {% set width = (cssWidth > maxCssWidth ? maxCssWidth : cssWidth) %}

        {# Determine the image size that 2X screens should get #}
        {% set width2x = (width * 2) > image.width ? image.width : (width * 2) %}

        {# Output the srcset= attribute value #}
        srcset="{{ image.getUrl(image.width != width ? { width: width }) }}, {{ image.getUrl(image.width != width2x ? { width: width2x }) }} 2x"

        {#- Output the width= and height= attributes if needed #}
        {%- if includeDimensions %} width="{{ width }}" height="{{ image.getHeight({ width: width }) }}"{% endif %}
    {% endspaceless -%}
{% endmacro %}

Adjust that {% set is2x = ... line based on however you’re identifying 2X images. For example if you’re going the Lightswitch route instead, it could be as simple as:

{% set is2x = image.is2x %}

Note that each of the image.getUrl() calls on the {{ output }} line are making sure that the width is different than the actual image width before passing the { width: X } object into getUrl() - that way we’re not having Craft go through the trouble of generating a transform unless we actually need to.

With that macro in place, now we just need to import it in our template, and start using it.

{% from _self import srcset %}

{# ... #}

{% for image in entry.myAssetsField %}
    <picture>
        <!--[if IE 9]><video style="display: none;"><![endif]-->
        <source media="(min-width: 1000px)" {{ srcset(image, 1000) }}>
        <source media="(min-width: 800px)" {{ srcset(image, 800) }}>
        <source media="(max-width: 320px)" {{ srcset(image, 320) }}>
        <!--[if IE 9]></video><![endif]-->
        <img {{ srcset(image, 600, true) }} alt="{{ image.title }}">
    </picture>
{% endfor %}

If you placed the macro in a different template, replace _self with the path to that template, e.g. "_macros".


Craft\Exception on saving entries having images

I'm going to go out on a limb and say you're trying to upload a file type that isn't allowed under that Asset fields "Restrict Allowed File Types?" section.


How to change an entry's slug on EVENT_AFTER_SAVE_ELEMENT?

You can change the value in the DB directly instead of using the Elements service

$entry = $event->element;
$elementId = $entry->id;
$siteId = $entry->siteId;
Craft::$app->getDb()->createCommand()
    ->update(
        '{{%elements_sites}}',
        ['slug' => ElementHelper::createSlug('new-slug')],
        [
            'elementId' => $elementId,
            'siteId'    => $siteId
        ]
    )->execute();

By the way the following condition [] !== $entry won't be any good when you fetch an element with one() because one returns an object of instance ElementInterface or null but never an empty array. You can check !== null instead and if you fetch things via all you can perform an empty check if( empty($entries) === false)


I would go for two loops to make it easier to maintain sanity later on:

{% set entries = craft.entries.section('country').level(3) %}

   {% for entry in entries %}

{{entry.pageTitle}}

   {% endif %}

   {% for entry in entries %}

{{entry.pageTitle}}

      {{entry.pageTitle}}

   {% endfor %}


What are the best-practices for useful logging messages?

If you're throwing Exceptions from your plugin, then those will automatically get logged in Craft's log files at craft/storage/runtime/logs with full stack trace information, so there is no need for extra logging there.

In you're using Craft::log or PluginHandlePlugin::log statements, and you set LogLevel::Error, or LogLevel::Warning, then those messages will get logged regardless if devMode is enabled or not.  LogLevel::Info and LogLevel::Profile will only get logged if devMode is enabled.

Logging the actual method name isn't really necessary because even with devMode disabled, you'll get a few steps in the stack leading up to the message so you can determine where it came from.  You will want to pass in any relevant variable names and values to the log message, though.


My month/year archive template code no longer works in 3.2

This should be fixed for the upcoming 3.2.11 release.

To get the fix early, change your craftcms/cms requirement in composer.json to:

"require": {
  "craftcms/cms": "dev-develop#87fd6ca6b0c57f524c8ccae895c13eb9724d0efa as 3.2.10",
  "...": "..."
}

Then run composer update.


Maybe it feels over the top, cause you could simplify your small request to something like this:

{% for page in craft.entries.section('about').all() %}

{{ page.title }}

{{ page.summary }}

{% endfor %}

Or, if you just want to get the title and the summary of that one single - you could archieve this via:

{% set aboutPage = craft.entries.section('about').one() %}

{{ aboutPage.title }}

{{ aboutPage.summary }}


Including a variant segment in product type template route in Commerce 2

Have figured out that instead of setting a template path in my product type I can leave that blank and use a custom route instead.

So in this case I set up a route for

/type/*/* -> shop/variant

It means I need to fetch the product entry manually in the template but that's no problem and it seems to be working.


If you are trying to get the top most parent entry of a child entry in a structure, you can use ancestorOf.

{% set parent = craft.entries.ancestorOf(entry).level(1).first() %}
<h1>{{parent.title}}</h1


Correct way to merge craft.user field arrays and use outside the loop?

It looks like you have a typo in your merge, and the structure of the merge is incorrect.

{% set merged = specialisms|merge(specialisms) %}

This is saying set merged to the array specialisms merged with itself.

What I am guessing you want to do is merge each specialism into the merged array, which looks like this:

{% set merged = merged|merge(specialism) %}

Note that we are merging specialism and not specialisms (no s at the end).

I'm not sure what data type specialism is, but if it isn't an array, you may need to wrap it in square brackets. This would become:

{% set merged = merged|merge([specialism]) %}

I hope this helps!


{basePath} creates a folder named {basePath} issue

Assuming this is using Craft 3, you should use aliases.

In your config/general.php add:

'aliases' => [
    'web' => 'https://site.com',
    'webroot' => dirname(__DIR__) . '/web'
],

Then in your Control Panel, under Settings → Assets → Images, set your Base URL to @web/images and File System Path to @webroot/images.


What's the template command to print available tokens?

Stick {{ dump(_context) }} in a template file to print out all the available values.

{{ dump(_context|keys) }} Outputs the keys of the array without going through it recursively.


Is it possible to configure the FileLogRoute?

Currently not without hacking the core files.

It's on our list to make log routing more configurable for Craft 3, though.


Force Download a file using an Ajax request or Task

I don't think you'll be able to use Craft's HttpRequestService->sendFile() for this.  But there are plenty of non-Craft ways of doing this, depending on your specific requirements.


How do I omit similar content in a for loop based on the first letter in title?

If you need only unique letters, you can build a new array and only merge first letters that are not already in the array like this:

{% set letterArray = [] %}

{% for alpha in craft.entries.section('advertisers').order('title asc') %}
  {% if alpha.title|first not in letterArray %}
    {% set letterArray = letterArray|merge([alpha.title|first]) %}
  {% endif %}
{% endfor %}

{% for letter in letterArray %}
  {{ letter }}
{% endfor %}


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

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


I was able to figure out how to get this working...See the following..

{% set entries = craft.entries.section('homepage, page').find() %}
{% nav navItem in entries %}

  {{ navItem.title }}

{% endnav %}


Ordering/sorting products by their variant stock level

Not possible at the moment, Craft would need to add better support for custom element sorting.

Can you please submit the request here so we can track it: https://github.com/craftcms/commerce/issues

This answer will be updated if there is a change.


Use Craft.postActionRequest in frontend template

The global Craft object available in the Control Panel is exposed in the craft.js file, which is a bundle containing most of the JavaScript code used in Craft's Control Panel (i.e. admin area).

This file is not meant to be used in your front end!

The craft.js file has dependencies on other CP-only JavaScript files, and weighs – by itself – a whopping ~250 kb minified, which is a lot of bytes to force on your end users just because you'd like to use a tiny part of the library in your front end code. Additionally, because the file is only meant to be used with core functionality in the Control Panel, it can be updated/changed by Pixel & Tonic at any time (i.e. any time Craft is updated), possibly breaking your custom code which depends on it.

Instead of using the whole craft.js package, I'd strongly advice you to cherry pick (i.e. copy and paste) any methods or functionality you need from craft.js to a custom JavaScript bundle. For specific functionality (e.g. AJAX requests), you might also consider using other, established open source libraries (like SuperAgent, Axios or even jQuery).


If you're doing it from a custom bootstrap script, you'd need to do something like this for plugin logging to work:

$craft = require '../craft/app/bootstrap.php';

craft()->plugins->loadPlugins();
MyPlugin::log('My Message', LogLevel::Error);
craft()->end();


Where can you set a form field to required in the DB

In Craft, fields can be shared across field layouts and there's no way to set a field as required across the board. A field can only be declared as "required" in the context of a field layout.

Usually this is easily done by clicking the cogwheel next to a field inside a tab in the field layout designer, and selecting "Make required". Sprout Forms uses the standard field layout designer, so you'll have this option here as well – though I'm guessing you have a specific reason for wanting to do it in the database.

In order to set a field (in a field layout) as required, first you'll need to know the field's ID. This is easily found by looking at the craft_fields table.

Next, you'll need to know the ID for the field layout you want to modify. In this case, you want the layout used by a specific Sprout Form, so the easiest way is to look at the fieldLayoutId column in the craft_sproutforms_forms table. For entries, you have to look at the craft_entrytypes table, for categories, you'll have to look at the craft_categorygroups table, etc).

Finally, you'll need to identify the field in the craft_fieldlayoutfields table, by looking at the layoutId and the fieldId columns. Set the required column for the appropriate row to 1, and you're done.


Modify how the html fields are outputted by Redactor

To add inline styles to HTML tags generated by Redactor such as <li>, install the Retcon plugin and add the following to your template. For example:

{{ entry.body | retconAttr('li', { style: 'color: red;' }) }}

For more info, consult the retconAttr filter documentation.


you should point your domain to the /web folder and not to the craft main folder.


Pass content of system messages to HTML Email Template

EmailService->sendEmailByKey() sets the htmlBody property of EmailModel to this:

$emailModel->htmlBody = "{% extends '{$template}' %}\n".
    "{% set body %}\n".
        $emailModel->htmlBody.
    "{% endset %}\n";

So if you've got a custom email template in craft/templates/email.html, in the control panel under Settings → Email → HTML Email Template, you'd set the value to email.html.

And you'd simply output the dynamic email content in your template by using {{ body }} like so:

<html>
    <body>
        <div>
            {{ body }}
        </div>
    </body>
</html>


Form elements need to have a name attribute.

<select name="submission" id="submission">
<option value="view">View</option>
<option value="submit">Submit</option>
</select>

<textarea name="content" rows="9" cols="80" id="content"></textarea>

That should do the trick!


Environmental variables for Scout plugin in scout.php file

If you use this, it should work:

\rias\scout\ScoutIndex::create(getenv('SCOUT_INDICES'))


Where do we get the SMTP Authentication information?

According to Microsoft, the Office 365 SMTP server is smtp.office365.com using port 587 and TLS encryption. Your username and password you'd get from your hosting provider as it's not Craft-specific information.


Can't login after installing Craft CMS 3

It was a permission issue. I used the command below on the entire craft folder to get this to work:

sudo chmod -R 777 craft/

The logs were saying that it didn't have permissions to open many files.


How to do multi-environment app config (config/app.php)?

To get this to work, have a look at the format of the general.php config file.

The key is to include the '*'=>[] at the start.


How to Make a Change to an Existing Page Go Live at a Particular Point in Time

Currently, there is not. I've dealt with this before and I actually created 2 pages, one with the future post date, and one with an expiry date. And so the future page will become active over the page that will expire, simulating the requested functionality (although this is not the preferred method, I concur)


Updating Craft cause broken git and merge conflict

The error that you are seeing is because you have changes in your local repo that need to be saved (committed) first.

I'm also a huge Git user and wanted to touch on a few items in your question.

The craft/app folder should always be in your Git repository as its the foundation of making your site run Craft.
If you want to see an example Craft Git project, you can take a look at this repository: https://github.com/themccallister/craft-foundation
The only directories that should be ignored are storage (make sure you keep the actually directory using this trick: https://stackoverflow.com/questions/115983/add-empty-directory-to-git-repository) and any directories in public that will contain user uploaded files (i.e public/images/uploads). This will ensure that the directory contents are not overwritten during deployment, ensuring that backups, sessions and user content will remain after the deploy.

As far as your remote build... The typical workflow for Git should look something like this:

Download and update Craft locally
Commit your changes to your local environment (should mostly be updates in the craft/app directory)
Push your changes to your remote repository (typically referred to as origin or upstream)
Deploy the update.

Note: If you are building using a tool like (http://dploy.io) you can login and push the changes to your environment. If you are SSHing into the server and running git pull origin that would work as well.


Can images embedded in a Rich Text field be resized on output?

If you create an image transform in the control panel, the client will be able to choose that transform when selecting an image (in the bottom right corner). But there's no way to get Craft to transform the image based on the size the clients manually set the image to be in the rich text field.


Is it possible to set any attributes (such as a class) of the `a` tag when using `getLink()`?

No, getLink outputs a very simple version of the link.

If you want something more complex, you'll need to build it manually...

{{ foo.title }}


HighRes image crop tool (not Aviary plugin)

Aviary is pretty heavy handed. I agree with you, it'd be great to have some tools in Craft to handle cropping. There's been some rumblings in the past of Craft 3 shipping with some new toys but that's a ways away. I don't know of any alternative but you could certainly build your own.

Use something like Jcrop then use some tools server side to crop the actual image. That's relatively straightforward.

Implementing it in Craft is the other tricky piece. Wonder if anyone else in the Craft community has tried doing something like this?


This was a complication due to using the same browser for different user testings. Once all semblance of my admin user session/cookies were absent, the admin styles and scripts no longer appeared on this page.


Grabing data from another channel associated to an entry displayed using category

You nailed it! relatedTo: 'entry' is indeed your issue. Two problems I see with it: 1) you're checking for things related to the string entry, which doesn't do you a lot of good, and 2) even if it wasn't a string you're not setting the entry variable anywhere.

Here's what you need to do:

{% set category = craft.categories.group('productCategories').slug(craft.request.lastSegment).one %}

{# we should only continue if we actually have a category #}
{% if category %}

    {# let's call this products to keep things simpler #}
    {% set products = craft.entries
        .relatedTo(category)
        .orderBy('dateCreated desc')
        .limit(30)
        .all() %}

    {# we need to loop over our products before we even start worrying about the reviews #}
    {% for product in products %}

        {# obviously here is where you'd add your html markup to display the products #}
        {{ product.title }}

        {# we now have a `product` variable to use as our relatedTo param #}
        {% set productReviews = craft.entries
            .section('userProductReviews')
            .relatedTo(product)
            .all() %}

        {# we can use the already existing query to get the total count (as opposed to sending off a whole new query) via the `| length` filter #}
        {% set reviewCount = productReviews | length %}
        {% set sumOverallRatings = 0 %}

        {# I've also renamed these variables to keep things easy to understand #}
        {% for review in productReviews %}
            {% set sumOverallratings = sumOverallRatings + review.overallRating %}
        {% endfor %}

        {% set productOverallAverage = sumOverallratings / reviewCount %}

        {# and now you have your average rating! #}
        {{ productOverallAverage }}

    {% endfor %}

{% endif %}

For bonus points, you could tidy up the part where you're querying and calculating the ratings (as long as you're on Twig 2.10+) using the reduce filter.

With reduce you could replace everything inside the {% for product in products %} ... {% endfor %} loop with this (and whatever html markup you're using):

{% set productReviews = craft.entries
    .section('userProductReviews')
    .relatedTo(product)
    .all() %}

{{ productReviews | reduce((totalSum, review) => totalSum + review.overallRating) / productReviews | length }}

The reduce filter here is taking your array of product entries and basically adding up the value of all the overallRating fields, which we then divide by the length of the productReviews array.


Set Variables from the Matrix Field - SEO

Twig's for function is scoped. This means that variables defined inside of it will not be accessible outside the loop.

What you need to do, is to declare the variable with an initial value before the loop:

{% set descr = null %}

{% for block in entry.matrix %}
    {% if block.type == "seo" %}
    {% set descr = block.metaDescription %}
    {% endif %}
{% endfor %}

{% if descr != null %}
    <meta name="description" content="{{ descr }}" />
{% endif %}

This works, because in Twig the inner scope (i.e. your loop) will have access to variables belonging to its parent scope, but not vice versa.


Why if I change ie. drop down value, all entries needs to be resaved to take changes? How can I prevent it?

Dropdown fields (and other simple option-based fieldtypes such as Radio Buttons, Checkboxes and Multi Select) are pretty dumb.

By design, whenever an Entry with a Dropdown field is saved, Craft simply grabs the selected value for that Dropdown field and stores it in the database for that Entry. Unlike relational fields such as Assets or Categories, there's no "connection" (i.e. relation) between the selected value being stored, and the Dropdown fields' option where the value was pulled from – this means that if you later decide to rename a Dropdown fields' option value from e.g. "foo" to "bar", the selected value for any existing entries will not change/update. In other words, any entries that had "foo" selected, will still have "foo" stored as their value for that particular field, even if that option doesn't exist anymore.

The easiest way to bulk update entries' selected Dropdown values is probably to execute an SQL query.

Something like the below should work (the following example would update the selected value for a field with the handle myDropdownField from "foo" to "bar", for all entries that have "foo" selected):

UPDATE craft_content SET field_myDropdownField = 'bar' WHERE field_myDropdownField = 'foo';

To run this query, you'll need some sort of SQL client – for Mac, Sequel Pro is very decent, and free. You can also use something like Adminer.

Oh, and don't forget to back up your database before running any manual SQL query, and to clear out your caches after you're done.


Development system with MAMP won't run after MAMP upgrade?

The ports were changed to 7888 and 8888 and I needed to set them back to what I was currently using.


For the sake of completeness, the question was resolved by the asker and I will quote his answer here, so this fine question is recognized by Stack Exchange as answered!

Matt V says:

  I discovered that the following works:

foreach ($user->networksMatrix as $key => $networkLink)
{
    $netArr[$networkLink->id]["fields"]["networktype"] = $networkLink->networktype->ids()[0];
    $netArr[$networkLink->id]["fields"]["networkUrl"] = $networkLink->networkUrl;
}

  Since networktype is a categories field and that field is limited to 1
  category I'll only ever get a single result from the method:

ids();

  So... I just do this and I'm good:

$networkLink->networktype->ids()[0];


Problem with truncated Freeform checkbox group value when mapped to another field

Currently, the Element Connections feature requires that a Freeform array field be mapped to a Craft field that also accepts an array (e.g. Freeform Checkbox Group to Craft Checkboxes).
I've made a note about this for us to revisit in the future though, and potentially add a transformer to handle this kind of mapping. :)


Display additional fields (and sort by) in Entries in Control Panel

Not at the moment. Sorting by custom field in the back end entries screen is not yet implemented although I know it is definitely possible in the future based on the way the code is currently laid out.

I would create a front end method to list and sort the entries with links into edit with cpEditUrl

http://buildwithcraft.com/docs/templating/categorymodel#cpEditUrl


Calling Related Entries using the Element API

You’d do this with a brand new element query using the relatedTo param.

Craft 2:

// This is the PHP equivalent of typing `craft.entries()` in a template:
$criteria = craft()->elements->getCriteria(ElementType::Entry);

// Only fetch Location entries that are related to the Site entry:
$criteria->section = 'locations';
$criteria->relatedTo = ['targetElement' => $entry];

$locations = $criteria->find();

Craft 3:

// This is the PHP equivalent of typing `craft.entries()` in a template:
$query = \craft\elements\Entry::find();

// Only fetch Location entries that are related to the Site entry:
$query->section('locations');
$query->relatedTo(['targetElement' => $entry]);

$locations = $query->all();


Using language specific variables inside section URL settings

Maybe include the .site in your query craft.entries.section('archive').site('YOUR_SITE_HANDLE').one()

What is the section type of your "Archive" entry ? If its a single, maybe it will be more effective to write the handle down manually instead of doing a Query every time.

Note: You can also use .siteId() instead of .site()


Undefined property: Craft\WebApp::$urlManager in /var/www/craft/app/controllers/BaseController.php on line 37

You're probably running PHP v. 7.0 or higher on your DigitalOcean box; Craft CMS didn't have PHP 7.0 compatibility until Craft 2.4.2697, which is why it chokes.

Downgrading your PHP version to 5.6 or 5.4 should resolve your issue.

You should also beware of your MySQL version – Craft 2 has issues on MySQL 5.7; ideally you should make sure your droplet uses 5.6.

And also – I'd look into upgrading the install to the latest and greatest Craft 2.x, if not Craft 3. A lot of good stuff has happened since 2014 ;)


Supporting LongBlob / LongBinary in Craft record ColumnType

Why is LongText supported but not LongBlob for Craft records?

Support, mainly... and there hasn't been a demand for it (you're the first to ask that I'm aware of).

Currently Craft's PHP based database backup logic chokes on MySQL datatypes that can't be represented as textual data.

For the upcoming Craft 3, we've done away with the AttributeType magic and you've got more direct/exact control over how your want your schema to be defined.

We also plan on updating the backup logic to be able to handle non-textual datatypes.

In the meantime, if you want this in Craft 2, you'll have to move that attribute/column out of an Active Record, create it with a migration and have your service layer use DbCommand to interact with it.


You should be using setContentFromPost() rather than setContent(), so that field types have a chance to prep the values that you are passing in.

See “What is getContent() / the ContentModel, and how do I use it to get and set custom field values?” for more info on how this stuff works.


How would I allow guests to add comments and ratings to existent entries?

Using the Guest Entries plugin, it is not possible. Using a custom plugin is possible though. The trick is that each guest needs to be identifiable in some way. Otherwise every guest would be able to edit every comment, and you would have chaos (or a wiki).

So if you want them to be able to edit a comment and still not have to log in, you can create a custom plugin that replicates much of the functionality of the Guest Entries plugin. Adding on to that, you could create a unique string stored in a separate table linked to that entry. This string would be used to give the anonymous user a unique edit link. This would keep the comment reasonably safe.

Though in all honesty, you would be better served by having users log in or using an external commenting service (if you are avoiding buying a higher Craft version).


Probably need a little more information (as in, an example of your feed), but if you're trying to import HTML content in an XML-based feed, you'll want to wrap that with CDATA, so its escaped properly.

<![CDATA[
This is bold
]]>


If I'm following you correctly, it should be as simple as this:

    {% if blog.myCategoryFieldHandle|length %}

            {% for category in blog.myCategoryFieldHandle %}

{{ category.title }}
            {% endfor %}

    {% endif %}


How do Twig filters interact with concatenated strings and shorthand "if-else" ( `var ? true : false` ) strings?

You are asking about Twig's operator precedence:

The operator precedence is as follows, with the lowest-precedence operators listed first: ?: (ternary operator), b-and, b-xor, b-or, or, and, ==, !=, <=>, <, >, >=, <=, in, matches, starts with, ends with, .., +, -, ~, *, /, //, %, is (tests), **, ??, | (filters), [], and .:

| is higher precedence than ~, so 'this' ~ 'that' | raw will evaluate as 'this' ~ ('that' | raw). If you want ('this' ~ 'that') | raw then () is the way to go.
Personally, I would use () to disambiguate in both cases.


Honestly, that's pretty much impossible to say, it could be pretty much anything – though a white screen is often due to PHP errors, in which case you might find a clue in your log files (located at /craft/storage/runtime/logs (search for [error]). Your web server's error logs might hold some clues as well.


You're overriding the "title" and "link" properties on every iteration. Wrap the itemObject object in [] to merge the whole object into your array.

{% set object = object|merge([itemObject]) %}


returning HTML in $event->sender->addErrors doesn't work

Allright, after digging & debugging a bit further into this issue I found it out myself!
$event->sender->addErrors([
    'expiryDate' => Template::raw('cpEditUrl.'>'.$entry[0]->title.'')
]);

PS: don't forget to add this to the top of your php file:
use craft\helpers\Template;


How to create single lines from a plain text field with line breaks

I've made a little macro for this:

{% macro splitText(text) %}
  {% set text = text|nl2br|raw %}
  {% set text = '' ~ text|replace('
', ' ') ~ '' %}
  {{ text|raw }}
{% endmacro %}

You may need to tweak it a bit, but this is what worked for me.


It has been answered in another thread here: enter link description here, but basically you have to use another focal point plugin called FocalPointField-Craft which then works with eager loading. And I've found also uses a lot less database queries than the other plugin too.


Adding an additional Download PDF to orders

As of Commerce 3.1.12 only the one PDF can be registered in general settings. We will be adding support for additional PDFs to be configured in the next release. Stay tuned.


Is it possible to use _includes/forms outside of the Control Panel?

I've been able to render CP templates in the front end using some methods in PathService and TemplatesService, which you could use inside your own Template Variable to render the macros:

class YourVariable {

    public function renderFormMacro($macro, array $args)
    {
        // Get the current template path
        $originalPath = craft()->path->getTemplatesPath();

        // Point Twig at the CP templates
        craft()->path->setTemplatesPath(craft()->path->getCpTemplatesPath());

        // Render the macro.
        $html = craft()->templates->renderMacro('_includes/forms', $macro, array($args));

        // Restore the original template path
        craft()->path->setTemplatesPath($originalPath);

        return TemplateHelper::getRaw($html);
    }
}

Which would be used like:

craft.yourVariable.renderFormMacro('textField', { label: 'Name' })

I've not tested it but I think that should be close.


'onDeleteEntry' Event is not triggered when an Entry is deleted?

Bulk actions do not trigger their respective events. When you delete an entry (or multiple entries) via the checkboxes, you are performing a bulk action.

As a workaround, you can listen to the onBeforePerformAction or onPerformAction events, check to see if the action parameter to see if it's the action you're interested in and perform  your logic as necessary. *

  * Much of this answer was copied from my & Brad's answers on this similar thread...


How do I set my siteURL instead of having http://localhost:8888/?

Unless instructed otherwise, MAMP uses port 8888. You can tell it to use the "default" ports, which will mean the site gets served over port 80, and your URLs no longer contain :8888.

As for the other issue, it sounds like you haven't set up your site's document root correctly. Either way, it's a MAMP configuration issue, not a Craft issue.


Craft causing Apache2 to max out memory and swap

I sent the Craft 2 database to Pixel and Tonic, and Brad kindly updated it for me.


Error reporting Freeform submission jumps to top of page despite auto form anchor

We've recently discovered that this feature is not always reliable unfortunately. However, we're working on addressing this and coming up with a better solution in the coming weeks. Sorry for any inconvenience.


How can I limit the output of assets randomly if an asset exists?

This is how you do it in case anyone is looking for this.

{% set assets = craft.assets.limit(null) %}

{% set randomEntry = craft.entries.section('homes').order('RAND()').relatedTo({
    targetElement: assets,
    field: 'homeImages'
}) %}

{% for homesEntry in randomEntry.limit(6) %}
    {% set asset = homesEntry.homeImages.first() %}

    {% if asset %}

    {% endif %}
{% endfor %}


How to speed up a single entry page with Eager Loading

Disclaimer: While eager-loading will almost always bring down the total number of queries executed, it's important to note that having less queries won't always equal better performance. When optimising a page with eager-loading, you should take care to observe the actual time Craft spends on database queries – which is the metric that matters.

For Craft 3, you should enable the Debug Toolbar, which will tell you exactly how many milliseconds Craft is using for database queries. Eager loading is not a silver bullet, and you should note the time spent on database queries with and without eager loading, to determine if it's actually increasing performance or not. You can enable the debug toolbar from your Craft user's profile page inside the Control Panel.

For Craft 2, you'll need to enable devMode, crack open your browser's dev tools console and expand the *Profiling Summary Report*. Unfortunately, AFAIK there's no record of the time spent on queries specifically, but you can gauge it by looking at the Time property (which will report the total time Craft spent resolving the request, including database queries). Obviously, the lower this number is, the better.

Furthermore, before worrying about eager loading, you should make sure that your template is properly optimised without it. The most important thing is to make sure that you're not doing multiple, redundant queries.

In the code example above, you're first executing two queries on the entry.imageGallery() field outside the {% for %} loop, and then 1 additional query per image inside the {% for %} loop. In other words, if you added 100 images to the galleryImages field, you'd execute a total of 102 queries – which is totally unnecessary.

By caching the array of Assets returned by .all() to a variable, you can get away with a single query:

{# Get all images in the field #}
{% set galleryImages = entry.galleryImages.all() %}

{# Set the `titleImage` to the first image #}
{% set titleImage = galleryImages[0] ?? null %}

{% if titleImage %}
    ...
{% endif %}

{{ entry.bodyText }}

{# Use the |slice filter to remove the first image – i.e. the title image – from the Assets array, and then print the rest of the images #}
{% set galleryImages = galleryImages|slice(1) %}

{% if galleryImages|length %}
    {% for image in galleryImages %}
        ...
    {% endfor %}
{% endif %}

Note the use of the |slice filter – this is used to remove the first index (i.e. the first image) from the array, after caching it to a variable titleImage. Don't worry, the |slice operation won't throw an error, even if the galleryImages array is empty.

With the above optimisation, your X number of queries have been reduced to a single query – and at that point, you probably wouldn't see any performance improvements by adding eager loading.

But, if you wanted to try it – here's how it could be done (this would replace the first line in the above example):

{% do craft.app.elements.eagerLoadElements(
    className(entry),
    [entry],
    ['galleryImages']
) %}

The above statement should go at the very top of your template – and if you do this, make sure to remove the reference to .all() in the first line of the first example (by eager loading the Assets field, the entry.galleryImages property is already an array and hence has no all() method).

Again, the above is probably not useful if you do the optimisations to bring down your query count to 1 – but, it could be useful if you had multiple relational fields you wanted to query, i.e.

{% do craft.app.elements.eagerLoadElements(
    className(entry),
    [entry],
    ['galleryImages', 'entriesField', 'categoryField']
) %}

For more info on eager loading, check out this excellent article.


How can I make make the class of an entry link "active" if entry is the current url?

You don't need to use Javascript/jQuery for this.
You can get the the current url from craft.app.request in some way and do a check as you output your navigation.
It looks like you have some custom fields for urls but, For instance, if you wanted to check the last url segment you could use craft.app.request.segment(-1) to get it. Then when outputting your css classes, check it against whatever and output the active class.
{% set currentPage = craft.app.request.segment(-1) %}

then in your loop...

    Some title

You can also get the full URL with {{ craft.app.request.absoluteUrl }}
Or {{ craft.app.request.pathInfo }} to get the path


Problems transferring updates back to live server

From Craft Support:
Assuming the credentials in your .env are correct on that site, could you run ./craft clear-caches/all (or manually empty your web/cpresources and storage/runtime


How Customizable is the Craft Admin Interface?

There are some ways to customize the Craft Control Panel interface, but probably not to the extent that you are looking for.

The native way to do this would be through the use of the not-at-all documented template hooks similar to this.

You can search through the craft/app/templates folder for {% hook to get a full list of hooks available and the templates they live in.

For a bit more kludgy solution, you could use plugins like CP CSS and CP JS for injecting arbitrary CSS/JS into Control Panel requests.

Also worth noting this from the license agreement when dealing with plugins that modify Control Panel functionality:

  You may not write a plugin that breaks or tampers with any of Craft’s built-in functionality, including any restrictions related to license/edition enforcement, its core feature set, or its Premium Features.


Getting Matrix content from within a relationship field

Twig is quite different from the EE parser – much more in line with how PHP is interpreted (Twig actually compiles to PHP before rendering).

First, the use of gallery in your for loop is arbitrary – its just the name you pick for the variable containing the currently iterated item, and its completely up to you. So this would work just as well:

{% for galleryEntry in block.galleryInclude %}
    {{ galleryEntry.title }}
    ...
{% endfor %}

Second, there are a couple of issues with your code. For one, you'll need to use another for loop to access the slides inside the galleryMatrix field. Note that you can use "block" as the variable name here as well (unless you need to access any of the outer block variable's properties), but let's call it "slide" for clarity:

{% for slide in gallery.galleryMatrix %}
    ...
{% endfor %}

Note that if your galleryMatrix field contains multiple block types and you're only interested in the "slide" block type, you can for test the slide.type property inside the loop, or use the type method to filter the galleryMatrix field:

{% for slide in gallery.galleryMatrix.type('slide') %}
    ...
{% endfor %}

Furthermore – this is a common gotcha for new Craft users – even if there's only 1 asset, you'll always need to loop through any Asset field; you can't just put assetField.getUrl(). So, you'll need another loop to pull your slide image(s) inside the galleryMatrix loop:

{% for image in slide.slideImage %}

{% endfor %}

Sidenote; when there's only a single asset you could also do the following, but as you'll need an if statement the amount of code won't be any less:

{% set slideImage = slide.slideImage.first() %}
{% if slideImage %}

{% endif %}

Putting it together, here's what your full code should look like (not tested, but should work based on the info you gave):

{% for gallery in block.galleryInclude %}
    {{ gallery.title }}

        {% for slide in gallery.galleryMatrix %}
            {% for image in slide.slideImage %}

            {% endfor %}
        {% endfor %}

{% endfor %}


When clicking blogposts it redirects me to localhost

You need to create an 'entry.html' file which lists the title, description etc.. within it. The link to the post should then direct you to the entry.html file.

/blog/entry.html


Creating a Custom Field Type with nested Fields

I don't believe you need a new custom field type for this. What your describing has been accomplished quite well already by the Neo plugin...

  https://github.com/benjamminf/craft-neo

Additionally, the Super Table plugin has similar capabilities...

  https://github.com/engram-design/SuperTable


Loop through matrix field find first block of a type

{% set myFirstMatrixBlockWithType = entry.blogPostMainSection.type('blogText').one() %}

{{ myFirstMatrixBlockWithType.articleText }}

Keep in mind entry.blogPostMainSection is not an array of blocks but a Query


Is it possible to clear caches and re-index assets programattically?

I guess it depends. So, behind the scenes, Craft can have different cache drivers. You might use the db or file cache, or something like Redis or Memcache.

Took a peek at ClearCachesTool, and it looks like it's doing the things you mentioned:

craft()->db->createCommand()->truncateTable('assettransformindex');
craft()->db->createCommand()->truncateTable('assetindexdata');

As well as deleting all the internal cache folders (runtime/cache, assets, compiled_templates, temp), including any plugin cache paths that have registered via registerCachePaths.

craft()->db->createCommand()->delete(static::$_templateCachesTable);

It also deletes the templates cache.

I guess what you're looking for are these:

CacheService->flush()
ClearCachesTool->performAction() (does most of the clearing)
craft()->templateCache->deleteAllCaches(); (called in ClearCachesTool - TemplateCacheService)

So yes, you can either bootstrap Craft and call a php file from the commandline, or add a plugin with an action that you GET/POST to after deployment.

The former, you can do with the included bootstrap.php file (as of 2.2)

$craft = require 'craft/app/bootstrap.php';


Massive template cache cleaning tasks always get stuck

As suggested by Fred, using the {% cache globally using key craft.request.path %} trick from https://craftcms.stackexchange.com/a/8335/342 gets rid of almost all duplicates!

But for the last few I notice that the duplicates all expire within seconds of each other, maybe this is an instance of https://en.wikipedia.org/wiki/Cache_stampede ?

I.e. several clients request the pages "simultaneously" and the page is rendered several times, and each version is cached?


Adjust the config to change the order of the formatting menu in Redactor II

Looks like the Redactor formatting config setting only affects what shows up or not from Redactor's default's of ['p', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5'].

Can't say whether that's a bug or intended behavior, but you could probably set the defaults to empty [], then add them back in the order you want with formattingAdd.


Importing members from EE without password reset

It would be possible to write a plugin that provides an alternative login controller action, based on UsersController::actionLogin(). The difference would be that, if normal login fails, it could try checking the old ExpressionEngine database to see if the user exists there, and if so, it could hash up the password in the same way EE does it, and see if it matches. When a password matches, the plugin could then A) update the user's password in the Craft database, and B) log the user in.

The only caveat (besides that this is a bit of work) is that it will only work for front-end login forms; you can’t change where the CP login form is submitted to.

So, your plugin would need a custom controller class, with the following code:

namespace Craft;

class CustomLoginController extends BaseController
{
    protected $allowAnonymous = true;

    public function actionLogin()
    {
        // Attempt to log the user in
        $this->_login();

        // Now pass back to the normal login controller
        craft()->runController('users/login');
    }

    private function _login()
    {
        if (craft()->userSession->isLoggedIn())
        {
            return;
        }

        if (craft()->request->isPostRequest())
        {
            $loginName = craft()->request->getPost('loginName');
            $password = craft()->request->getPost('password');
            $rememberMe = (bool) craft()->request->getPost('rememberMe');

            // Try logging them in normally
            if (craft()->userSession->login($loginName, $password, $rememberMe))
            {
                return;
            }

            // Is it an actual user account, at least?
            $user = craft()->users->getUserByUsernameOrEmail($loginName);

            if ($user)
            {
                // See if they had an EE user account
                $host = craft()->config->get('server', ConfigFile::Db);
                $port = craft()->config->get('port', ConfigFile::Db);
                $dbName = 'ee_database_name';
                $dbUser = 'ee_database_username';
                $dbPass = 'ee_database_password';
                $db = new DbConnection('mysql:host='.$host.';dbname='.$dbName.';port='.$port.';', $dbUser, $dbPass);

                $row = $db->createCommand()
                    ->select('member_id, password, salt')
                    ->from('exp_members')
                    ->where(array('or', 'username=:login', 'email=:login'), array(':login' => $loginName))
                    ->queryRow();

                if ($row)
                {
                    $hashedPassword = $this->_hashEEPassword($password);

                    if ($hashedPassword == $row['password'])
                    {
                        // Eureka! Now update the local user account
                        $user->newPassword = $password;
                        craft()->users->changePassword($user);

                        // Delete the old user row so their old password stops working
                        $db->createCommand()->delete('exp_members',
                            array('member_id=:id'),
                            array(':id' => $row['member_id']));
                    }
                }
            }
        }
    }

    private function _hashEEPassword($password)
    {
        // Hash the password using EE's hashing technique
        // ...

        return $hashedPassword;
    }
}

The actual code that would go into _hashEEPassword() depends on your EE version. In EE 3.1 it lives in system/ee/legacy/libraries/Auth.php, function hash_password(). Not going to repost it here as it is copyrighted, though.

With the plugin in place and installed, you can start pointing front-end login forms to the new controller action by changing the action hidden input value:

<input type="hidden" name="action" value="customLogin/login">


Trying to show selected categories in a multi select form input

When you do currentUser.occupation.all() your selected variable is an objet so your conditional {% if category.id == selected %} will never pass as you are checking if category.id equals an object.

For this to work, first get the ids of the currentUser occupations:

{% set selected = currentUser.occupation.ids() %}

Which would return an array of ids (key/value pairs) then you compare doing:

{% if category.id in selected|values %}

So in full:

    <select multiple name="fields[occupation][]" class="selectpicker" >
        {% for category in categories %}
        {% set selected = currentUser.occupation.ids() %}
          <option value="{{ category.id }}" {% if category.id in selected|values %} selected{% endif %} > {{ category.title }} </option>
        {% endfor %}
    </select>


Image are returned as an array so could use either of the following:

{{ content.img[0].url }}

Or set a variable which fetches the asset to then output its fields

{% set asset = content.img.first() %}
{{ asset.url }}

Related: Looping through images in a Asset field type

UPDATE: The line {% if content.img|length %} will always be true because you are checking for existence of the field. You need to instead check that the field has a value using one of the methods below:

{% for content in entry.contentBuilder.type('imgHeader') %}

    {% if content.img[0]|length %}
        {{ content.img[0].url }}
    {% else %}
        default jpg
    {% endif %}

{% endfor %}

or

{% for content in entry.contentBuilder.type('imgHeader') %}

    {% set image = content.img.first() %}

    {% if image|length %}
        {{ image.url }}
    {% else %}
        default jpg
    {% endif %}

{% endfor %}


Image transforms returning cpresources url

That’s what getUrl() returns if the transform hasn’t been generated yet. When the browser requests that URL, Craft will generate the transform, and respond with a 302 redirect to the actual image URL.

Update: As of Craft 2.2, even if the transform generation URL doesn’t get directly requested (e.g. if it’s a social media image, or a srcset size that doesn’t apply to the browser), it will still get generated automatically as a background task as soon as Craft is done serving the page.

The next time getUrl() gets called (after the transform has been generated), the image URL will be returned directly.

If you would prefer that getUrl() actually generates the transform itself and immediately returns the image URL (perhaps because the output is getting cached by Varnish or something), you can open up craft/config/general.php and add this to your config array:

'generateTransformsBeforePageLoad' => true,

(See http://buildwithcraft.com/docs/config-settings#generateTransformsBeforePageLoad for details.)


Display first image from matrix field of a related entry to current tags

I think entry.matrixFieldHandle.type('blockTypeHandle') is what you're looking for. Putting it together, it'd be something like:

{% set tag = entry.keywords %}
{% set relatedEntries = craft.entries.relatedTo(tag).id('not ' ~ entry.id).limit(8) %}

{% for relatedEntry in relatedEntries %}

    {% set matrixBlock = relatedEntry.matrixFieldHandle.type('blockTypeHandle').first() %}

    {% if matrixBlock %}

        {% set asset = matrixBlock.imageFieldHandle.first() %}

        {% if asset %}

            <h1>{{ relatedEntry.title }}</h1>
            {{ asset.img }}

        {% endif %}

    {% endif %}

{% endfor %}


ImageOptomize and SEOmatic - Is Image Variant Required for Social and SEO images?

I've used SEOmatic and ImageOptimize together before and never had those issues. SEOmatic should care less about the presence of the ImageOptimize field on the asset and you definitely don't need to specify custom ImageOptimize variants for your SEO/social purposes. SEOmatic grabs the raw image (like you would grab the asset url in the templates) and does its own transforms to get that image ready for social/SEO use.

My guess is something is incorrectly setup in the Content SEO settings for whatever section the entry you're currently editing exists in. If you still can't figure it out, I'd be curious to see screenshots of those settings...

Also, fwiw, Andrew does provide a very handy SEO Settings field that might be worth considering as a replacement to the setup you've got going on currently. As he mentions in the plugin README:

  Modern SEO works best if it actually reflects what is on the page, visible to the user, so pulling from your page's content will work well in most cases.

So what I've done (and would recommend, though it would mean you would lose your client-friendly field descriptions) is to pull the SEO/social data out of the content of the page and then add the SEO Settings field to that last tab just in case you need to overwrite stuff. For example, rather than adding the asset used as the masthead image and the asset used for SEO/social separately, use the same field for both. Makes it simpler on the client and on you! And then, if and when you do need a different image for the social/SEO metadata, you can use the SEO Settings field.


Ok found the solution to this.

All input fields must have the following format fields[handle] - i was just using the handle!

Example:

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


What happens when extending an extended template?

So I tried it, made three files, one extending the first, and another extending the second, and it all worked more or less as one would expect.

bozo.html

<!DOCTYPE HTML>
<html>
  <head>
    {% set title = title ~ 'Main' %}
    <title>{{ title }}</title>
  </head>
  <body>
    Where was {% block whereWasBozo %}Bozo?{% endblock whereWasBozo %}<br>
    Variable A is {{ a }}
  </body>
</html>

ex1_bozo.html

{% extends 'bozo.html' %}
{% set title = title ~ 'Bozo 1 = ' %}
{% set a = 'ex1' %}
{% block whereWasBozo %}
  Bozo wasn't here.
{% endblock whereWasBozo %}

ex2_bozo.html

{% extends 'ex1_bozo.html' %}
{% set title = 'Bozo 2 + ' %}
{% set a = 'ex2' %}
{% block whereWasBozo %}
Bozo was in Bozoland.
{% endblock %}

When I pulled up page ex2_bozo.html, the end result was the page title said:

Bozo 2 + Bozo 1 = Main

and the web page said:

Where was Bozo was in Bozoland.
Variable A is ex1

So the blocks extend all the way through. The variables are first set in the file you initially call. They are modified in the middle 'extension' and modified again in the final extension.


How to use alterColumn to change the values of an ENUM field in a DB Migration

Something like this should work:

$this->alterColumn('tableName', 'columnName', "enum('existingOption1','existingOption2','newOption') NULL");


I see what you're asking. Instead of using SuperTable, you could create a block type that has two rich text fields in it, Column 1 and Column 2. Alternately, you can create a separate channel for repeating content types (a CTA, for example) and make a block type that simply relates to that content (block type is 'entries').


It does it per default:

public function getInputHtml($value, ElementInterface $element = null): string
{
    return Craft::$app->getView()->renderTemplate('_includes/forms/select', [
        'name' => $this->handle,
        'value' => $value,
        'options' => $this->translatedOptions(), //<-- here are your translated options
    ]);
}

But you need to insert your translations into your translation files for the site category

protected function translatedOptions(): array
{
    $translatedOptions = [];

    if ($this->options) {
        foreach ($this->options as $option) {
            $translatedOptions[] = [
                'label' => Craft::t('site', $option['label']),
                'value' => $option['value']
            ];
        }
    }

    return $translatedOptions;
}


Is this Craft 2 or Craft 3?

There are a few of ways to get entries but basically you could do something like (Craft 3)

use craft\elements\Entry;

$entries = Entry::find()->status(null)->all();

To find all disabled entries.


Most email service providers like MailChimp won't let you send to a list of addresses, even if they're user accounts on your site, without first adding them to a list inside the ESP's control panel.
If you're planning on sending out user emails through a tool like this, it's best to determine the sync strategy before you start signing up users.
That said you have a couple options for existing users:

Create a template to export your user information in CSV format, save it's output and import into MailChimp

Use the Campaign Plugin to send out messages


I think you are going to struggle with this in Craft, you would need to do it through Javascript.

Craft runs off PHP which is a server side scripting language, you need a client side scripting language.

Here is a good question which should help you with this: Get the size of the screen, current web page and browser window


How can I conditionally resave entries based on the value of an entry's field in a Craft 3 Module/Plugin?

My working solution:

public function actionResaveEntries()
{
    $site = Craft::$app->sites->getSiteById(self::SITE_ID);
    $section = Craft::$app->sections->getSectionById(self::SECTION_ID);
    $entryType = Craft::$app->sections->getEntryTypeById(self::ENTRY_TYPE_ID);

    $entries = Entry::find()
        ->siteId(self::SITE_ID)
        ->sectionId(self::SECTION_ID)
        ->typeId(self::COMP_ENTRY_TYPE_ID)
        ->all();

    foreach ($entries as $entry) {
        // Set deadline
        $deadline = $entry->competitionJudgingEnd;
        // Check if after deadline
        $now = new DateTime();
        if ($now > $deadline) {
            Craft::$app->getQueue()->push(new ResaveElements([
                'description' => Craft::t('app', 'Resaving {section}, {type} entries', [
                    'section' => $section, 'type' => $entryType->name,
                ]),
                'elementType' => Entry::class,
                'criteria' => [
                    'siteId' => $site->id,
                    'sectionId' => $section->id,
                    'typeId' => $entryType->id,
                    'status' => null,
                    'enabledForSite' => true
                ]
            ]));
            echo "Resaving entries\n"
        } else
            echo "Not resaving entries\n";
        }
    }
}


Looking for tips on cleaning up craft_content and craft_entryversions tables after spam attack

Assuming the SPAM posts came through in a contiguous block, one semi-easy way would be to restore the 300k entry database locally on a Craft install.

Then you could do a SQL query like:

DELETE FROM `craft_elements` WHERE `id` IN (
    SELECT `id` FROM `craft_entries` WHERE`dateCreated` BETWEEN '2017-02-01 00:00:00' AND '2017-02-02 00:00:00'
)

Adjusting the dateCreated values for the beginning and ending of the SPAM posts.

The cascading deletes on the foreign keys that Craft use will kick in and clean up all of the content in the related tables like craft_content and craft_entryrevisions (as well as others).

Then you could restore that cleaned-up database back to production.


How to determine if a user's email has changed

Only thing I can think of off the top of my head would be to create a new, separate database table that stores user Ids against email addresses. Perhaps also with a timestamp of when the row was written.

You can then write the user's email address to that upon registration and use it to check against the "official" email address when you need to.

If you find a change, do whatever it is you need to do and update your table with the new email address.


Sorry about the trouble. We typically answer most tickets within 24 hours:

Freeform: https://solspace.com/craft/freeform/support/
Calendar: https://solspace.com/craft/calendar/support/

If the Support Form isn't working for you, you can always email us directly at support@solspace.com :)


Craft 3 - Recommended development environment for Windows?

First of all, I am also a Mac user. But these should be available for Windows too.

Start reading about virtualization. So, you won't install the web server directly on your machine but on a virtual box installed on your machine.

A good starting point could be vagrant (which is becoming a bit antiquated more and more, but which is still worth a try since it's working like a charm).
What's getting more and more into many developers' focus is docker. Many of my customers have been introducing it in their developer teams the last years.

Hope that helps. It's a lot to read though…


Does Craft enforce a maximum filesize for large files?

The only thing Craft enforces is the maxUploadFileSize config setting, which by default is set to 16MB.  Outside of that, any limitations you run into will be environmental/server config related.


How can I set up a filter URL like example.com/category/foo/type/bar/country/usa

The parameterized paths (as opposed to the queries) implies a certain hierarchy. According to Google's SEO document, you have to anticipate that users will cut a part of the URL off. What happens if they cut out "usa", but "country"?

What you're doing right now is filtering/searching, not creating a hierarchy. So, you're complicating your own routing (making it more likely to fail and thus hurting your SEO even further), and not conveying the information particularly accurately.

If you want the parameterized URLs as opposed to query strings, you'll want to reorganize your URL structure to be hierarchical -- i.e. - products/shirts/tshirts -- and drop off the "parameter names" that you're trying to shoe-horn in.

Also, consider whether that particular page actually needs to be indexed by search engines, and if it needs to be indexed with the query string. Can you simply allow it to be indexed without any filtering? Does it need to be indexed at all? If you don't need to index it, then you can keep the query string for human usability, and tell spiders not to index it at all. If you don't need to index it as filtered and going to the page, without a query string, results in the non-filtered content, then most spiders will do that by default.

For example, look at google.com, before and after a search. Obviously, search result pages don't need to be indexed (nor would you want to, because that would result in a ton of botched indexed), but the main page, itself, probably should be. As a result, they use a query string that includes q=searchstring on their search results page.


Something like this should work:

`craft()->runController('pluginHandle/controllerId/action');`

Although I'd question the decisions you've made to get to the point where you had to ask this question. ;)


Help understanding an error message from Dukt OAuth plugin

It was indeed missing files, as suggested by Alec and Benjamin. All down to some non-specific .gitignore rules that meant it was ignoring all "src" folders - which is one of the folders created by the composer install

Thanks for your help guys!


Search/return entries with custom field length less than 200

I'm not 100% sure what you are trying to achieve but If its because all the others would be to big for whatever you're building. You could use Hacksaw to fit all your text.

https://github.com/ryanshrum/hacksaw


How do you route an entry or category URI to a plugin controller?

You want to take a look at the registerSiteRoutes() method in your plugin class. In this example, it will route a request to your MyPluginHandle_FooController::actionBar() method. foo is obviously the name of the controller, and bar is the method.

public function registerSiteRoutes()
{
    return array(
        'some/route/here' => array('action' => 'myPluginHandle/foo/bar'),
    );
}

Here is what the controller would look like with these naming conventions:

<?php
namespace

class MyPluginHandle_FooController extends BaseController
{
    // Allow anonymous users (users that aren't logged in) to use this controller
    protected $allowAnonymous = true;

    public function actionBar()
    {
        // do something
    }
}

You can also do the same thing for CP routes.

http://buildwithcraft.com/docs/plugins/templates#dynamic-url-routing


Is it possible to restrict assets in multi region/site specific similarly to how you can restrict entries?

Currently Asset Volumes in Craft 3 are defined on a global basis.  If you would like to see differently, you can create a feature request and be sure to include your use-case.

Asset fields have advanced settings where you can relate Assets from a specific site or not in the Control Panel under Assets->Fields->(your Asset field)->Advanced


Sprout Forms - Can't save front end entry edits

Craft 3

This feature is available in Sprout Forms for Craft 3 (since v3.0.0-beta.22).

The feature is disabled by default and can be enabled in the Sprout Forms settings.

Craft 2

This feature exists in Sprout Forms for Craft 2 via the enableEditFormEntryViaFrontEnd config override.


Where did the @property delcarations for the inbuilt services go?

The bad news is it's been a bug in PHPStorm since 9.0.1.

The good news is it's been fixed in the PHPStorm 11 EAP and will be in the 11 final release.

https://youtrack.jetbrains.com/issue/WI-28394


Is it possible to move an entire asset source?

The easiest way I imagine would be to

Create a local folder
Download all the files into the folder (outside of Assets - via Transmit or similar)
Change your source settings from S3 to Local with correct paths

And you're done. Whoa, that was easy :)


Is it possible to limit the number of times a user can be added to the same field across different entries?

Could you not come at it from a different angle and instead choose your team by editing the user? That way you can assign a team field to the user and restrict that field so that you can only pick the one team.

Then in your templates you can use relations to link them all up.


How to set entries to auto-expire after certain # of days from post date?

There's no build in functionality for this, but you could make a custom plugin that automatically sets the expiration date expiryDate when you first save an entry with a specific entry type.

Another option would be to simply filter your entries from your template:

{% set entries = craft.entries.type('myEntryType').postDate('>= ' ~ now|date_modify('-10 days')) %}

.

Edit:

Here's a description for the expression used as the value for the date_modify parameter.

Have a look at the syntax for parameter values in the Craft docs. And also how the date_modify filter works. now|date_modify('-10 days') returns a string which is then concatenated with the string '>= ' and then passed as a value to the postDate() parameter.


You would usually display the image with

{% for pageImage in entry.pageImage %}

{% endfor %}

But this only works if you enabled the public url option for the asset source. There is a light switch if those assets should have urls or not in your cp

It also has a getImg() function

/**
 * Returns an  tag based on this asset.
 *
 * @return \Twig_Markup|null
 */
public function getImg()
{
    if ($this->kind == 'image' && $this->getHasUrls())
    {
        $img = 'getUrl().'" width="'.$this->getWidth().'" height="'.$this->getHeight().'" alt="'.HtmlHelper::encode($this->title).'" />';
        return TemplateHelper::getRaw($img);
    }
}


MySql 5.7 error - field doesn't have a default value

The STRICT_TRANS_TABLES mode was added to the default SQL mode in MySQL 5.7.5 and is likely causing the error to be thrown:
https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html

You can either disable STRICT_TRANS_TABLES mode in your database (there are plenty of articles explaining how), or add default values to your fields (which I would recommend).


By default Craft checks the postLoginRedirect setting in your config. Depending on this value the user is going to be redirected to certain place. But if there is a value in the user session that's set when the requireLogin function is called Yii2 will use this value instead. So the workflow is the following

Check for a session value, if there is one, redirect the user
Check for postLoginRedirect value, if there is one, redirect the user
Redirect to homepage

  Using a return parameter in the login form does not work for obvious reasons.

Could you explain those obvious reasons? Because I always use the returnUrl from UsersController when I create a login via ajax.

You don't have to do anything actually. Just include the Twig token and Yii2 will handle it


Craft 2: Serve language / locale i18n according to user agent

You could accomplish this before your PHP is executed as redirects listening for the accept_language header (both are untested from my part):

APACHE

RewriteEngine on
RewriteCond %{HTTP:Accept-Language} (de) [NC]
RewriteRule .* http://example.com/de/ [R,L]

NGINX

map $http_accept_language $lang {
  default en;
  ~de de;
}

location ~* "/" {
  return 302 https://example.com/$lang;
}


How to find and delete with Active Record

Have you tried

$instance = new Calendar37Record;
$instance->deleteByPk($id);


Deleting stale template stuck fatal memory error

Anything in queue.log that gives us hints? Anyway if it is just the stale template caches task... I'd just truncate the cache tables manually (n.b.: truncate, not delete):

templatecaches

You only need to truncate that one cache table, because it'll cascade can remove the other related columns in templatecacheelements and templatecachequeries as well.

Then I'd truncate the queue table as well to remove the no longer needed stale template cache queue jobs.

Learn more:

Zen and the Art of Craft CMS Log File Reading
The Craft {% cache %} Tag In-Depth


Verbb Feed Me for Craft 3 - Possible to read assets from local disk?

Files and assets are two different concepts. An asset represents a file already in Craft, and you'll be able to search and browse for it in the Assets section. Whereas in a number of different cases, you'll want to create (upload) an asset from a URL.

If you have an existing asset in Craft already, so you don't want to upload it, then provide just the filename and extension in your feed. This is as per the documentation.

If you want to create an asset from a remote URL, you'll need to tick the "Create asset from URL" checkbox in the mapping screen for Feed Me. If you do this option however, you'll need to provide an absolute URL to the file you want to import into Craft.

So, with the above in mind, the short answer to your question is that Feed Me doesn't support creating assets from a local path, but it does support it from a local URL. You'll need to change the path in your feed to point to a full URL, which you can achieve by moving it to a folder in your project, or setting up a virtual host in your favourite local dev environment.


Is it possible to provide an option to pick up an order from the physical store in Craft Commerce?

You could make 'pickup from store' a shipping method.

Then in your checkout form, if a visitor chooses that shipping method, make sure you don't show the shipping address form, and add a hidden input to set order.shippingSameAsBilling to true. Commerce will then populate the shipping address with the billing address details. Code is untested, but it should be something like:

{% if order.shippingMethodHandle == 'pickupInStore' %}
    {{ hiddenInput('shippingSameAsBilling', 1) }}
{% else %}
    {# Show the shipping address form #}
{% endif %}


How to reference specific asset subfolders in Craft 3

Have a look at the folderId parameter. https://docs.craftcms.com/v3/dev/element-queries/asset-queries.html#parameters

To find which id your folder has, it looks like you have to look in the assets table - someone might have an easier solution.