Verify if unrelated items are in the cart Folks:

In this scenario, a main product has multiple accessories (which are, of course, related to the main product through relationships). Only certain accessories are related to the main product. The user can place main products and unrelated accessories into the cart. I'd like to display a warning that they are ordering incompatible items.

I understand that you can use empty or relatedTo to find out if a relationship exists between entries but in this case, I need to know if accessories unrelated to the main product are in the cart.

Is this possible?

In essence, if I am reading that right, can you reverse the question?  I.e. it seems that what you want to know is, for each accessory in the cart, is there a reverse relation back to at least one product in the cart.

This is definitely possible - you can read about reverse relations here: https://straightupcraft.com/articles/introduction-to-relations-and-reverse-relations-in-craft-cms-with-examples and of course at https://craftcms.com/docs/relations

..basically just loop through each accessory and check the |length of the result of a relatedTo that specifies what you want it to be related to (.e.g a product category).


Craft Commerce: Agree to Terms Checkbox? What would be the best way of adding an Agree to Terms checkbox during the the checkout process of craft commerce? I'm thinking this would be best in the address section.

We've implemented this using front end JS, simply don't allow submission until it is ticked, but you could (and/or) in theory add a field to your orders and then validate it as set during the onBeforeSaveOrder event I guess?  If not set, you'd set $event->performAction to false to stop the order being saved and show an error in your template.

https://craftcommerce.com/docs/events-reference#commerce_orders.onbeforesaveorder

...but frond end JS is probably going to be the easier route here.


Form tabs aren't saving in the Sprout Forms plugin Strange bug: I'm creating tabs in a new form, but they're not saving. Goes like this:

Create a new tab
Re-name tab
Save form (to add / create a field)
Newly created tab is gone

Same thing happens whether it's my form or one of the default example ones ("basic" and "contact"). The "basic" form has two tabs; I checked the db to see if the tab data (names, number, etc.) is saved anywhere there but I can't see any table that contains it.

So maybe it's stored in a file somewhere? Which means maybe some kind of permissions issue? Much obliged for any guidance.

OK, heard from Barrel Strength / Sprout support. His reply:

  Please create any fields that you need before adding the tab, then
  please go ahead and add the tab(s) then drag and drop the fields that
  you need into the new tab (rename the new tab in this step if you
  want) and finally save the form. The new tabs need to have at least
  one field to be saved with the form.

Since you can't create an empty tab, the trick is to create all your fields first -- or at least, one field per tab. Then, after you create the tabs, you can drag a single field to each tab and save the form. That will keep the tabs. After that, when you create a new field, you can select the tab it belongs to in the dropdown.

I think that's how it also works in the native Craft field manager? So hopefully this helps somebody even if you're not using Sprout Forms (which is awesome, by the way.)


Display entry category I know this is a really suck egg question, but I finding the Craft docs far less straightforward than EE (I'm just switching over), and so I'm struggling with the easy task of displaying an entry's category.
{% for entry in craft.entries.section('blog').limit(1) %}

{{ entry.title }}

   {% if entry.byLine %}

{{ entry.byLine }}

   {% endif %}

Category: { ???? }

   {% endfor %}

Can anyone help?

To display a single category you'll need to do something like this:
{% set category = entry.categoryfieldhandle.one() %}
{{category.title}}

To display multiple categories:
{% set categories = entry.categoryfieldhandle.all() %}
{% for category in categories %}
{{category.title}}
{% endfor %}

Replace categoryfieldhandle with the handle you used for your field.
You can find more in depth and alternative ways in the docs:
https://craftcms.com/docs/3.x/relations.html
Since you're new to craft I recommend taking a look at the following course https://craftquest.io/courses/craft-cms-3-tutorials to help get you started.


FeedMe - all sites get overwritten by other foreign sites import, even though fields are translatable per group I have about 16 sites added to my Craft CMS install. They are grouped together by language, so for example, I have 6 sites in English, and 4 sites in Spanish, 2 in German, and then some individual ones.

I have set the Sections to "Propagate entries across all enabled sites?" because when we create a new site, or a new entry, say in Spanish, we would want all the same pages created and connected to other pages in other sites, and would be expecting the pages to be in the language of the group the site was in.

I have a matrix field in which I have set some fields to translate per site group, and others to be not-translatable.

If I import the main US site first, it goes well, then if I import say German next, it seems all sites content is updated to German. but all other sites are in a different group.

I am sure I did not have this issue before when importing.

Editing and saving an entry in German does not then change the US, so its just when importing.

I have previously read when importing Matrix it does not update fields within it, but deletes it and re-creates it. So is it doing this on all sites?

How can one set the main matrix field to be translatable per group so it does not get touched in other groups? The only option is "Manage blocks on a per-site basis" which we would not want, as it needs to be the same per group. I assume there should be a field "Manage blocks on a per-group basis"?

Thanks

This is expected behavior when importing Matrix blocks, currently. See my comment on craftcms/feed-me#463 for a full explanation and possible workaround.


Available updates not displaying on local copy but show up on live site; instead displays "You're all up to date!" with 5 pending updates When I attempt to display available updates on my local copy, Craft is unable to display them and instead shows “You’re all up-to-date!”.

Available updates do display on my live copy, as well as on the “updates available” badge on the local copy CP.

I’ve cleared the cache to no avail and I’ve checked the logs and can’t see any errors. I'm running an nginx server and am starting to wonder if this problem arose when switching from apache -> nginx.

I am currently running version 2.6.2996 and am trying to update to 2.6.3001 as well as update a few plugins.

Has anyone run into this issue while trying to display updates on their local copy CP?

The responses coming back when I hit the updates page were all 200s and allowAutoUpdates was set to true using the default setting.

Adding my comment as an answer because it fixed my issue:

I traced the issue to a deprecation warning involving $HTTP_RAW_POST_DATA being populated.

I added the line always_populate_raw_post_data = -1 to my fpm_app.conf which solved the issue.


Sending an email before entry expires Entries in a particular section have expiration dates of up to one year away. The client would like to receive a notification email two weeks before this expiration date is reached.

Here's a bonus question: These entries are connected to another section of vets. Each vet entry will have an email field. Whatever vet is connected to the original entry in question (the one with the expiration field) also needs to receive this notification email.

Are there any existing plugins that allow this? I haven't found any yet.

Thanks!

I'm not aware of any existing plugins that would do this, and it seems pretty use-case specific.

You can do this with a custom plugin and a cron job, though.

The cron job would run every 1/5/x minutes, hit an action in your plugin's controller and that action could get the entries in the section you're interested in, check the post date and decide what to do from there.


Multilingual google problems I’ve set up a multilingual craft site.
My primary site is BE and base Url is set to /
The two other ones are NL which base Url is set to /nl and LU which is set to /lu
All the three website have en-US as a language.
When I google my website and I say I speak Dutch, the only website that is showing is the NL version. It’s not even showing the BE or LU version.

Any way I can change this?

Thanks in advance!

Apparently SEOMatic provides an automatic hreflang to your source.
So changing the language in the settings tab helped for me.


Using ElementType as field type for plugin in what way do I provide my own data to the modal? I have been looking at the BaseElementFieldType.php file to try and understand how to use it for my own field type. How do I provide that field type with my own array of data to use? I believe it has to do with the sources,criteria, or elements but it is unclear to me.

Ah, in that case you'll need to make your own ElementType. You should probably check out https://github.com/pixelandtonic/Events - that's meant to be a simple ElementType to serve as an entry point while we get some documentation together.

Also, there are some videos to watch over here: http://buildwithcraft.com/docs/plugins/working-with-elements#creating-new-element-types


Commerce - show description of discount without coupon applied to cart We can retrieve description of discount applied to cart that has its own coupon like this:
craft.commerce.discounts.getDiscountByCode(cart.couponCode).description

Is it possible for discount that do not have coupons and are applied automatically?

I suspect there is a much better way, but I use something like this, looping over all cart adjustments, checking the type of adjustment.
We use the adjustment.sourceSnapshot for the coupon code, otherwise access the attributes on the adjustment directly, which is a Discount model.
        {% for adjustment in cart.adjustments if adjustment.type == "discount" %}
            {% set isCoupon = adjustment.sourceSnapshot.code ??? false %}
            {% if isCoupon %}
                Coupon: {{ adjustment.sourceSnapshot.code }}
            {% else %}
                {{ adjustment.name }}<br />
                {{ adjustment.description }}
            {% endif %}

         {% endfor %}

...that works.
Documentation, such as it is, is here:
https://craftcms.com/docs/commerce/3.x/adjusters.html#adjusting
And the available attributes for a discount model:
https://docs.craftcms.com/commerce/api/v3/craft-commerce-models-discount.html#app
(or src: https://github.com/craftcms/commerce/blob/master/src/models/Discount.php)
(Honestly, though, even looking at the documentation now, it's really not obvious how to come to this code....)


Migrations: What's the right way to rename a Foreign Key? I'm writing a migration for one of my plugins, and struggling to resolve something which should theoretically be simple:

$this->renameColumn('myplugin_mytable', 'oldId', 'newId');

Except that doesn't work, because the column is a foreign key. The migration fails, and it kicks out this error in the log file:

  2016/02/07 20:09:29 [error] [application] CDbCommand failed to execute the SQL statement: SQLSTATE[HY000]: General error: 1025 Error on rename of './mysite/#sql-95d9_1e' to './mysite/craft_myplugin_mytable' (errno: 150). The SQL statement executed was: ALTER TABLE craft_myplugin_mytable CHANGE oldId newId int(11) NOT NULL (/craft/app/framework/db/CDbCommand.php:358)

Googling around, it seems that this error happens when you attempt to alter a foreign key.

I tried this method as well:

dropForeignKey for "oldId"
renameColumn from "oldId" to "newId"
addForeignKey for "newId"

But unfortunately, that's not working smoothly either.

What is the right way to rename a foreign key?

Sidenote: I'm tempted to post a feature request for P&T to add a renameForeignKey method to the MigrationHelper class. If that seems like the right approach, I'm happy to submit that feature request and we can close this question.

The 2nd method you tried is the correct order to do it in.

Call BaseMigration->dropForeignKey() ($this->dropForeignKey from within the context of a migration).
Call BaseMigration->renameColumn() ($this->renameColumn).
And add the column back with with BaseMigration->addForeignKey() ($this->addForeignKey).

If you received an error during any of those steps, it's likely because MySQL is complaining about inconsistent data among the FK endpoints or the endpoints are of different data types.

EDIT BY OP

The final version of the code looked like this:

$table = 'myplugin_mytable';
$this->dropForeignKey($table, 'oldId');
$this->renameColumn($table, 'oldId', 'newId');
$this->addForeignKey($table, 'newId', 'myplugin_related', 'id', 'CASCADE', 'CASCADE');


Title field only available I am currently working through the demo site Happy Lager and installed another separate instance of Craft from github as provided from the Craft site.

I am creating ‘modules’ and adding fields etc..

But

When I try to add an entry all I get is the title field. Even on the dashboard there is no option of including fields for population. Could you advise what seems to be the problem, the demo works fine and i’m especially interested in using the matrix functionality of the field functionality.

But all I get is the title field when I try to add an entry and have experimented with matrix and stand alone fields

From reading your question it seems like the fields haven't been added to your entry type for the section you are trying to add entries to.

The first thing I'd recommend doing is to go to Settings > Sections then find the section in the list you are trying to add entries to.
You should see an Entry Types column at the right; click on the Edit entry type option for the section.

This part of Craft allows you to add the fields you would like available in your entry. You can create your own tabs to categorise your fields as you see fit.

All you will need to do is drag the fields from the bottom of the screen into your field layout.

Go back to the entry and hopefully the fields you added will be showing!


Can I Configure Redactor to Automatically Add a Class to Img Tags? I am trying to set up lazy loading for the images on my site but currently, any image added via Redactor lacks the necessary 'lazyload' class.

Is there any way to configure Redactor to automatically add this class to any image added through Redactor? I have been digging through the documentation on their site and doing some googling but so far haven't found anything.

Found this plugin doing some digging https://github.com/mmikkel/Retcon-Craft. It looks like it can achieve what you need - appending existing attributes (including class names) by applying a filter to your Redactor field in your Twig template.


How to use LDAP for authentication in Craft CP (back end) Where only users in Active Directory can login to the Craft Control Panel.

There's a feature request here that would allow custom login forms for the Craft Control Panel login page you might want to add a comment to.

In the meantime, there is a userSession.onBeforeAuthenticate event a plugin can listen to to perform any 3rd party authentication.

You can see how a similar plugin did this for front-end LDAP logins here:
 https://github.com/thepitagroup/adldap_craftcms


How to plan IA for a directory of content thats good for admins and users I want to build a directory of fishing ports
It will have approx 500 entries, each geocoded for map display.
I will have 4 views;
1) Directory with map of entries
2) Country and entries
3) Cities (Ports) and entries
4) Port entry

Issues I have at this stage.

a) how to structure countries,cities and fishing ports?
admin will struggle to find stuff to edit if they have to page thru 500 entries  when entries have similar names "Stella maris centre" exists in Netherlands and Australia, denmark etc.  How can an admin distinguish the correct entry to edit?
This assumes I am using categories for country and city storage.

b) I want the url structure to be "directory/country/city/fishing-port-name"
Assuming I can use custom routes with categories to create my urls, i run into the issue above in a)

So should i create entry types for countries and cities and use them in heirarchy so admin can enjoy ease of finding stuff?

Planning around this is becoming a head spinner :)

a) There are a definitely a few ways to handle this, but I would recommend the following. Put your Countries and Cities in a category group, nesting cities inside countries. Your Fishing Port section should be a Structure, since the entries are not time dependent like entries in a Channel. All you would need is a single category field that relates the fishing port to a city.

b) This can be done with custom routes, as long as each Fishing Port entry is related to one city category.

As for organizing the entries in the admin, you can make use of the modify entry sortable attributes and the modify entry table attributes hooks, which allow you to add an attribute in the sort dropdown and add different columns to the entry view. With this, you can add a City and Country column to the structure listing.


pass block into embed and forward to another embed? I'm trying to achieve some modularity using embeds, but with the possiblity to extend/inject customizations from the including template.

Consider the following scenario:

Have a modular partial which contains a form, say form.twig
I want the ability to add new form fields at the end of the form, but using the otherwise common form.twig, so I add a {% block form_extension %} in form.twig

I have another page template, that includes/embed that partial, say page.twig. Now, this works, I just add a block when embedding, and it gets injected.

But, I also have another modular partial, say partial_with_form.twig, that embeds form.twig. And I want to be able to define the form_extension block, when embedding partial_with_form.

Is this even possible? I have tried with parent() and block(), but none of them can give me the content of the supplied block unless I specify the targeting block in partial_with_form. But then it will be outputted there...

If partial_with_form.twig isn’t making any of its own customizations to form.twig, then I’d just include the form.twig template using an {% include %} tag, and wrap that whole thing with a {% block %}, so if a template wants to include the partial and make changes to the form, they can just redefine the form themselves.

partial_with_form.twig:

{% block form %}
  {% include 'form' %}
{% endblock %}

Other template:

{% embed `partial_with_form` %}
  {% block form %}
    {% embed 'form' %}
      {% block form_extension %}
        <!-- ... -->
      {% endblock %}
    {% endembed %}
  {% endblock %}
{% endembed %}


Loop based on date (with math) I would like to loop through entries only if the current date/time is before 5am on the following day from when the entry's eventDate (custom field mind you)is.

In other words I may have an event at 10pm on May/1/2015 and i want to loop through that date as long as it is not 5am (or later) on May/2/2015.

What I have currently is this:

{% for slide in craft.entries.section('events').featured('1').order('dateTime asc').limit(5).find() if (slide.dateTime|date("c","+8hours")) >= now|date("c") %}

However as you might have guessed, as far as i understand it, this loops through all entries as long as the current date/time is less than 8 hours AFTER the date/time of the event entry.

So to my understanding (Based on what i have observed) this will loop the entry up until 6am May/2/2015 which is not what i want.

In short. I'd like to ignore the 'time' portion of my date/time field as if it were May 1, 2015 12:00AM and add 29 hours, rather than including the time parameter of my date/time field and doing the math based on that which outputs variable results based on the time of the event.

Please let me know if i need to clarify any, I hope i've been clear. Also please let me know if there is anything else wrong with my For loop, it seems to work exactly how it should minus the date issue, but i'm always open to improvement.

You could try using the date_modify filter with a relative DateTime format:

{% if slide.dateTime|date_modify('tomorrow 5am')|date('U') < now|date('U') %}

And if you want to limit the entries to be displayed, you should not use the limit parameter for that. Your
ElementCriteriaModel doesn't take your DateTime conditional into account, so it requires a custom solution:

{% set slides = craft.entries.section('events').featured('1').order('dateTime asc').limit(null) %}

{% set count = 0 %}
{% for slide in slides %}
    {% if count < 5 and slide.dateTime|date_modify('tomorrow 5am')|date('U') < now|date('U') %}
        {{ slide.dateTime }}
        {% set count = count + 1 %}
    {% endif %}
{% endfor %}


How do I add an HTML block from template extension to main layout template? (i.e. meta data) I have a main layout file and extending it with another template. I have my markup and content in the {% block content %}{% endblock %} however, I'd like to add content to another "block" on the individual entry page for meta data - that would require adding another {% block content %} to my template as it would need to be output in a different area of the layout template.

Essentially, is there a way to add a second block (perhaps name it differently) or is my best bet to set all that meta data as a variable and pass it that way?

Option A: Set individual properties in the child template

If you want to set specific meta properties instead of defining a block, you can include lines like this in _layout.html:

{% if metaDescription is defined %}<meta property="description" content="{{ metaDescription }}">{% endif %}
{% if metaKeywords is defined %}<meta property="keywords" content="{{ metaKeywords }}">{% endif %}

Then, you can simply set either value from within the child template...

{% set metaDescription = entry.summaryFieldOrWhatever %}
{% set metaKeywords = entry.tagField %}

Option B: Pack an array with properties in the child template

...or as you pointed out, that could get cumbersome if you have a whole bunch of meta data. In that case, you could take a similar approach with an object instead of a block. So in _layout.html:

{% if metaProperties is defined %}
     {% for prop in metaProperties %}
     <meta property="{{ prop.name }}" content="{{ prop.value }}">
     {% endfor %}
{% endif %}

In the child template, then, you could...

{% set metaProperties = [
    { name: "description", value: entry.summaryFieldorWhatever },
    { name: "keywords", value: entry.tagField }
] %}

This way, you could set as many items as you'd like and still avoid passing markup to the parent template.

[EDIT] Typo fix


Deleting all entries from a Section I'm using Feedme to add entries via an external JSON feed.
There was an issue with matching duplicates and now need to remove >4000 entries from the site.

To avoid further issues would ideally like to build this into the feedme script we are running but the built-in delete method times out due to memory issues. I've looked at other ways we can achieve this, eg by deleting via the entries model:

$entriesRecord = EntryRecord::model()->findAllByAttributes(array('sectionId' => $sectionId));
$entriesRecord->delete();

But this is also timing out. Mike Pepper pointed me in the direction of the a&m command add-on at https://github.com/am-impact/amcommand but this is also struggling. Is the only way to deal with such large quantities of entries to do this directly via SQL?

Help!

Records are definitely not the way to go with dealing with large amounts of data sets in the database.  There is just too much overheard associated with them.

Manually running SQL (as you've discovered) is an option, but if you wanted to do this from PHP, you could still use QueryBuilder.

$elementIds = craft()->db->createCommand()
            ->select('id')
            ->from('entries')
            ->where('sectionId = :sectionId', array(':sectionId' => 18))
            ->queryColumn();

$rowsAffected = craft()->db->createCommand()
            ->delete(
                'elements',
                array('in', 'id', $elementIds)
             );

The MySQL cascading deletes setup on the foreign keys should take care of cleaning up the necessary rows in the remaining tables automatically.


Importing tables and Tablepress like plugin functionality Is there a plugin or something equivalent to Tablepress (WordPress) for Craft?

I have some large Excel table containing product pricings amongst other things, that I would like to import into Craft and manage there.

How do you plan to manage it in Craft?

If you want each row as a separate entry, create a section to hold the data, setup the fields you want to use to match each column, then use Bob Olde Hampsink's import plugin to bring in the data. The plugin allows you to map the data to the fields in Craft.

Craft supports tables natively but you need a way to import them. You can use Bob's import plugin but you'll need to use the plugin's hooks to get the data where you want it. Tables in Craft are stored as JSON so you have to do some data wresting.


Multiple Asset Field Query I'm looking to see if there's a better way of querying multiple asset fields in one query, surely there is but I just can't seem to find it in the docs.

      {% for asset in entry.eventMediaTile.all() %}

      {% endfor %}
      {% for asset in entry.eventMediaTriplet1.all() %}

      {% endfor %}
      {% for asset in entry.eventMediaTriplet2.all() %}

      {% endfor %}
      {% for asset in entry.eventMediaTriplet3.all() %}

      {% endfor %}
      {% for asset in entry.eventMediaTriplet4.all() %}

      {% endfor %}
      {% for asset in entry.eventMediaTriplet5.all() %}

      {% endfor %}

It may not be suitable for your use case but you could use an Asset query to fetch assets related to your entry:

{% set assets = craft
    .assets()
    .withTransforms(['eventImage'])
    .relatedTo({
        sourceElement: entry,
        field: ['your','fields']
    })
    .all() %}

{% for asset in assets %}
...
{% endfor %}

(If these are your only asset fields on the entry, you don't need field: ['your','fields'])


Is it possible to upload a zip file via Assets? I have a need to be able to upload a zip file into assets. Is it possible?

Yes, you can upload zip files from the main Assets table in the control panel as well as from an Assets field type assuming 1) you haven't removed 'zip' from the allowedFileExtensions config setting and 2) you haven't restricted the allowed file types in the field's settings.


addFieldVariables not functioning with string data I have the following code:

    {% set query = {} %}

     {% if not craft.request.getParam('q')|length %}
          {#.. key, value pairing .. #}
          {% set query = query | merge({(key):(value)}) %}
     {% else %}
          {% set query = craft.request.getParam('q') %}
     {% endif %}

     {% set queryStr = query|join(' OR ') %}

     {% do craft.sproutForms.addFieldVariables({ queryStr: queryStr }) %}

     {{ craft.sproutForms.displayForm('requestcsv') }}

When I add {{queryStr}} to my hidden field in requestcsv, it doesn't populate. I can output {{queryStr}} on the page, and even so, it doesn't get passed.

Is there something I'm missing in order to be able to pass this string to a hidden field? {{queryStr}} is just a plain string.

The value you place in your Hidden Field settings gets treated as a template and whatever values you pass o the addFieldVariables method are treated as the object that gets parsed by that template.

Just like, when you load an Entry page in Craft, Craft provides the entry variable to the template, when we process the Hidden Field settings, Sprout Forms provides the addFieldVariables variables to that template.

While Craft knows it is giving you an Entry and names it's variable entry, Sprout Forms doesn't really know what you might be giving it, so it names the variable available to your settings template a generic term: object.

You can access these values using Object Syntax, in the same way you can using the Title Format behavior for Sections:

{{ object.variableName }}

Or in your case:

{{ object.queryStr }}

In some cases, you can also use a shorthand to output the value with a single curly brace: {queryStr}.


Get saved sub category on user I have my users setup with a category field that links to a category of countries and each country has states/provinces.

I have my form setup to only display the states listed under United States. The plugin I created saves this data as expected.

The problem I'm having is accessing the state which was saved for the user. This is my current code. It works BUT there has to be a better way:

{% if user.addressMatrix | length %}

    {% for addressInfo in user.addressMatrix %}

        {% set cat = addressInfo.region[1] %}

        {{ cat.title }}

   {% endfor %}

{% endif %}

Please advise and thanks in advance.

Ok so I figured out the issue. I had the category field setup to have a limit of 1, which I assumed would be ok. My thinking was that you're only choosing 1 state. But because state is a sub category of country I need to allow for country and state AKA a limit of 2. Once I did this I was able to structure my template accordingly:

{% if user.addressMatrix | length %}

    {% for addressInfo in user.addressMatrix %}

         {% if addressInfo.type == "address" %}

            {% for item in addressInfo.region %}

                {% if item.level == 2 %}

                {{ item.title }}

                {% endif %}

            {% endfor %}

        {% endif %}

   {% endfor %}

{% endif %}

I think that future releases of Craft ought to have more options for category fields, like: Restricting selections to a sub category, limiting the number of sub categories.


Adding alt text/title attributes to assets in a rich text field I have custom fields for altText and title on some asset image locations.

Wondering if there is a good way to have those automatically added when a user puts in an image from a rich text field.

Nothing native that I can think of other than ditch the rich text field and use Matrix with a proper Assets field.


Can I use Regex in the Find and Replace tool? Does the Find and Replace tool support regex? I need to remove a certain section of an image url for all images in the 'field_body' column.

So if I had an image referenced as such

http://craft.dev/uploads/image-600x400.png

I would be able to find all images that match that pattern and return the url to be

http://craft.dev/uploads/image.png

Now I have very little experience with Regex but would this be a safe pattern to use (if I can with Craft that is...)?

(-[0-9]+x[0-9]+)

Nope, because MySQL doesn't support RegEx replacements in SQL statements.  It's been an open feature request since 2007, so feel free to add your vote.

There are some potential workarounds listed here, too.


How to build a multipage form using Freeform? I've been trying to search for some instructions on how to build a multipage form using Freeform in Craft CMS.

The official documentation is very light on the subject; https://solspace.com/craft/freeform/docs/multi-page-forms/ and there seems to be a general lack of information on the subject elsewhere.

Can anyone explain the steps I need to take in order to create a multipage form?

The form I'm creating is 2 pages in total. I need it to validate page 1 when the 'Next' button on page 1 is clicked, and then validate page 2 and submit the entire form when the 'Submit' button on page 2 is clicked.

Can anyone help or point me in the right direction to some information on the subject?

Actually, the templates that are provided in the docs over here are a pretty good place to start. You can change the markup, but you need the javascript:; tag in the a href=to get the multi-steps working.

Like any other form, I would suggest that you use some front-end validation. There are some nice libraries out there that get you up and running pretty quickly.

Are there any specifics you're struggling with?


'An unknown error occurred.' when trying to add new custom widget I am hoping that somebody can help with this issue.

I followed this excellent tutorial on creating a custom widget in Craft. On completion, I uploaded the plugin to the /craft/plugins/ directory, visited the page at /admin/settings/plugins and installed the plugin. All fine so far. Then, on returning to the dashboard, I clicked on New Widget, and selected the name of the widget. Following this, a message flashed up saying 'An unknown error occurred.' and little else happened.

It's probably user error, but if you could point out what I might have done incorrectly, that'd be useful.

My Plugin Structure

The plugin's called Adlister and the widget's called Alu, so in /craft/plugins/adlister/ I have two folders ( templates/ and widgets/ ), and a file: AdListerPlugin.php. Within templates/ is a file: AluWidget.html and within widgets/ is AdLister_AluWidget.php.

File Contents

AdListerPlugin.php

<?php
namespace Craft;

class AdListerPlugin extends BasePlugin
{
    function getName()
    {
         return Craft::t('AdLister');
    }

    function getVersion()
    {
        return '1.0';
    }

    function getDeveloper()
    {
        return 'Mark Syred';
    }

    function getDeveloperUrl()
    {
        return 'http://www.sypo.uk';
    }
}

AluWidget.html

Click to perform a daily update.

Click to perform an update on a Monday.

Click to perform a weekly update.

Click to perform a monthly update.

AdLister_AluWidget.php

<?php
namespace Craft;

class Adlister_AluWidget extends BaseWidget
{
    public function getName()
    {
        return Craft::t('Adlister Update');
    }

    public function getBodyHtml()
    {
        return craft()->templates->render('adlister/AluWidget');
    }
}

Any help that anyone could provide would be much appreciated.

With kind regards,

Mark

UPDATE

I don't know if this has any bearing, but the version of Craft I'm running is 2.6.2911.

I feel quite embarrassed, but I have finally got this thing working. The error that I had made was within AdLister_AluWidget.php. I had written at line 4: class Adlister_AluWidget extends BaseWidget instead of what it should have been: class AdLister_AluWidget extends BaseWidget. So, AdLister should have been written with an UPPER-CASE 'L' and not lower-case. If anyone else is struggling, hopefully my error will help them.

The correct code in full:

<?php
namespace Craft;

class AdLister_AluWidget extends BaseWidget
{
    public function getName()
    {
        return Craft::t('Adlister Update');
    }

    public function getBodyHtml()
    {
        return craft()->templates->render('adlister/AluWidget');
    }
}


Displaying variable in array in array = Impossible to access an attribute ("date") on a string variable ("") I'm trying to display a saved date from a json file.
I currently have:

{% set batchRowStats = craft.analytics.loadSavedBatch() %}

{% for stat in batchRowStats %}

        {{ stat['senddate'].date }}

{% endfor %}

And the information in the JSON file is:

[{"batchid":368,"total":1111,"opened":0,"clicked":0,"optout":0,"bounced":0,"subject":"subject line","senddate":{"date":"2017-06-02 06:00:22.000000","timezone_type":3,"timezone":"UTC"}}

I am getting this error:

Impossible to access an attribute ("date") on a string variable ("").

Which I am assuming it's because this information may be in a DateTime or object of sorts. I really need to just display "June 2, 2017" with a date_format but I'm not even sure how to get the string to display.

I attempted to get senate directly and output one element of it but no matter what index/key I set it would give me an error. Also, trying to change the object (or whatever it happened to be) in the PHP caused errors as well. I needed up just doing |first and |date to grab the date I needed and format it. The timezone_type and timezone were being converted into dates (December 1969 and current date) for some reason.

{% set batchRowStats = craft.analytics.loadSavedBatch() %}
{% for stat in batchRowStats %}
    {{ stat['senddate']|first|date("F j, Y") }}
{% endfor %}

I did change on thing in the PHP. I added (array) before the object inside of the array it's in. There are more complications to this scenario but I was assigning it to another variable and adding it to a different array. No matter what way I tried to extract the variable it would give me errors. String conversion gave me array error and array conversion usually gave me a string error and several others along the way. After placing (array) in front of it while assigning it to a variable it seemed to behave a bit better.

$emptyDateArray = (array) $innerResults['BatchStartDate'];


Updates always error out Every time I try to run an update, I get these errors. Installing plugins won't work either. I'm using Media Temple / Grid server hosting. I've increased the file size limits in php.ini as well. But I'm at a loss.
Status: Internal Server Error

Response: PHP Fatal Error 'yii\base\ErrorException' with message 'Out of memory (allocated 226500608) (tried to allocate 4096 bytes)'
in /nfs/c07/h01/mnt/179491/domains/bluepearl.villas/vendor/composer/composer/src/Composer/DependencyResolver/RuleWatchGraph.php:52
Stack trace:
#0 [internal function]: yii\base\ErrorHandler->handleFatalError()
#1 {main}

It looks like Media Temple Grid accounts are limited to 99MB of memory for PHP: https://mediatemple.net/community/products/grid/204643740/cgi-and-php-resource-limits
My guess is that they are ignoring whatever values are set in php.ini for memory_limit, but you can contact them to verify.


How do I get the column headers of a table in a matrix? I'm trying to write a general purpose matrix template and I've come up on a little snag with tables fields. I see no way to get the column header values.

The answer here mentions craft.fields.getFieldById(block.fieldId) but that doesn't appear to exist according to the documentation, nor did it work properly.

The closest I've gotten is this dirty slice job and that only gives me the ids of the columns. So I can do some string manipulation to get them close to the value but they can be completely different as well.

{% set first = block.table | first %}
{% set columns = first | keys | slice((first | length) / 2, first | length) %}

Any ideas would be helpful!

I'm trying to accomplish this:

<table>
  <thead>
    {{ loop through table headers }}
  </thead>
  <tbody>
    {{ loop through table data }}
  </tbody>
</table>

Updated code to output the entire table (headers and data).

Try this:

{% set entry = craft.entries.section('sectionHandle').first %}

{% for block in entry.matrixFieldHandle %}

    {% for field in block.getFieldLayout().getFields() %}

        {% set type = field.getField().type %}

        {% switch type %}
            {% case 'Table' %}

{{ field.getField().name }}

                            {% set columns = field.getField().settings.columns %}
                            {% for col in columns %}
                                {{ col.heading }}
                            {% endfor %}

                            {% set handle = field.getField().handle %}
                            {% set tableData = block[handle] %}
                            {% for row in tableData %}

                                    {% for key, col in row if key|slice(0,3) == 'col' %}
                                        {{ col }}
                                    {% endfor %}

                            {% endfor %}

        {% endswitch %}

    {% endfor %}

{% endfor %}


Are there any beginner Craft tutorials? I've been building sites with ModX Revolution for about 4 months but I've heard great things about Craft. I downloaded and installed it and the interface looks great.

To perform a detailed evaluation, I need to dive in and start building a basic site. But I don't know where to start. I found the mijingo tutorials but I have to pay $39.00 then mijingo tells me that I can only get so far with a free Craft license. To get the full experience, I need to buy at least a client license.

Are there any beginner tutorials for Craft that are free or at least don't require me to commit to the client Craft license?

Thanks.

Testing all Craft versions:

  If you would like to try out Craft Client or Craft Pro before buying,
  you can do so by running your site from the host name craft.dev.
  Subdomains work as well, e.g. site1.craft.dev.

See: How can I try Craft Client or Craft Pro before buying?

Tutorials:

Mijingo's Learning
Craft - Most comprehensive tutorial
Basic of templating in Craft
Twig Primer
Twig for Designers - A work-in-progress book from Brandon Kelly
Templating in EE vs. Craft

Examples:

P&T has demo files for two sites on github, which you can install locally:

HappyLager
On the Rocks

Resources:

Craft Cookbook - Code Snippets
Straight up Craft - Articles / Link lists / Tweets / Plugin List


Where should I add the file to write the code for the `afterSend` event for contact form plugin? I am using the contact form plugin in Craft CMS 3. I want to add the afterSend event. Where should I add the file to write the code for the afterSend event?

You should add it to custom-made module.

Go to https://pluginfactory.io/ to generate your module scaffolding (you don't need to select any additional components like models, variables etc for this), then install it accoding to instructions in readme file.

After that, attach to event in module init() function:

    public function init()
    {
        parent::init();
        self::$instance = $this;
        Event::on(Mailer::class, Mailer::EVENT_AFTER_SEND, function(SendEvent $e) {
           // custom logic...
        });
    }


Creating dynamic array and set keys I have content which needs to go into a certain column so I have a field called 'column' there. I can create the array I want by hand:

{%
    set items = {
        1 : {
            0 : 'Quick Facts',
            1 : 'Agencies'
        },
        2 : {
            0 : 'Inspiration',
            1 : 'Industry Experience'
        }
    }
%}

Where 1 and 2 are the columns, and 0,1 is just a normal index. In a loop it is different. I have tried the same syntax but of course setting the variable in the loop will set the new variable every time and replace the old one. Using merge like below always gives me new keys. Is there a way to do this as easily as PHP?

{% set blocks = {} %}

{% for tab in tabs %}
    {% for key,block in tab.tabItem %}

        {% if block.type == 'about' %}
            {% set blocks = blocks|merge({ (block.column.value) : block.aboutTitle}) %}
        {% endif %}

    {% endfor %}
{% endfor %}

This is the output of the two pieces of code (first being what I want). I'd like the block.column.value to be the key.

You can do this using the twig attribute function:

{% set data = [
    {'column':'1','title':'Quick Facts'},
    {'column':'2','title':'Inspiration'},
    {'column':'1','title':'Agencies'},
    {'column':'2','title':'Industry Experience'}
] %}

{% set cols = {} %}
{% for item in data %}

    {# create a dynamic property if one doesn't exist #}
    {% if not attribute(cols, 'col' ~ item.column) is defined %}
        {% set cols = cols|merge({ ('col' ~ item.column) : [item.title] }) %}

    {# else update the dynamic property with the new title #}
    {% else %}
        {% set titles = attribute(cols, 'col' ~ item.column) %}
        {% set titles = titles|merge([item.title]) %}
        {% set cols = cols|merge({ ('col' ~ item.column) : titles }) %}

    {% endif %}
{% endfor %}

{{ dump(cols) }}

{#
array(2) {
    ["col1"]=> array(2) {
         [0]=> string(11) "Quick Facts"
         [1]=> string(8) "Agencies"
    }
    ["col2"]=> array(2) {
        [0]=> string(11) "Inspiration"
        [1]=> string(19) "Industry Experience"
    }
}
#}


Impossible to invoke a method on a null variable I call a asset like this:

{% set headImage = entry.geschaeftsbereichHeadImage.first() %}
<img src="{{ headImage.url(headBanner) }}"

If I don't ad any image to this field there is a twig error:

  Impossible to invoke a method ("url") on a null variable

When I don't ad any Image to this field in the CP shouldn't there be just no image? Why the error? If I ad a image it works just fine.

Well, the first method only tries to get an asset model. But if there's no asset added to the field it simply returns null. So calling a method like getUrl, or accessing a property like url or title can't work, as they do not exist for null.

{% set image = entry.geschaeftsbereichHeadImage.first() %}

{% if image %}

{% endif %}

Or if you'd like to display a fallback image consider somthing like this:

{% set image = entry.geschaeftsbereichHeadImage.first() %}
{% set imageUrl = image ? image.url(headBanner) : 'path/to/fallback.jpg' %}


How to get a Super Table relation in PHP? The following code works great in a template.

{% set priceProduct = currentUser.priceTable.relatedTo({
    targetElement: product.id,
    field: 'product'
}).one() %}

{{ priceProduct.price }}

Where priceTable is a Super Table, product.id is from an entry element (we're in loop).

'product' is an entry field in the Super Table row and 'price' is a plaintext field in the Super Table row.

How might we go about replicating this functionality in a plugin?

Craft Pro 3.0.29

Super Table 2.0.11

$element = Craft::$app->getUser()->getIdentity()->priceTable->relatedTo([
    'targetElement' => $product->id,
    'field' => 'product'
])->one()

But to be honest your code in Twig should not work as expected since you only grab the query and modify it. Your output is your search criteria, not the value of an element.


Fetch all unused assets? How could I go about fetching all assets that are not currently beeing used anywhere?

With good help from @carlcs here and on Slack, we found a solution:

{% set allEntryIds = craft.entries.limit(null).ids() %}

{% set usedAssets = craft.assets({
    relatedTo: allEntryIds,
    limit: null,
}).ids() %}
{% set unusedAssets = craft.assets({
    id: 'and, not ' ~ usedAssets|join(', not '),
    limit: null
}) %}


Where can you set a form field to required in the DB Can someone point me to where in the DB you set a field as required? I am actually wanting to do this on a Sprout Forms field I am not sure if that makes a difference or not. I can't find which table you would do that in.

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.


Create Structure on Plugin Install I'm trying to create a structure using onBeforeInstall() that will be ready for a client to use after the plugin is installed.

Here's my code for onBeforeInstall():

public function onBeforeInstall()
{
    $section = new SectionModel();
    $section->name = 'Demo';
    $section->handle = 'demo';
    $section->type = 'structure';
    $section->hasUrls = 1;
    $section->template = 'demo/page';
    $section->enableVersioning = 1;
    $locale = craft()->sections->getSectionLocales(1)[0];
    $locale->urlFormat = 'demo/{slug}';
    $locale->nestedUrlFormat = '{parent.uri}/{slug}';
    $section->setLocales([ $locale ]);

    $response = craft()->sections->saveSection($section);
    if ($response) {
        var_dump("IT WORKED!");
        var_dump($response);
    } else {
        var_dump("nope.avi");
        var_dump($response);
    }
}

Unfortunately I get a CDbException

  CDbCommand failed to execute the SQL statement: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`craft`.`craft_sections_i18n`, CONSTRAINT `craft_sections_i18n_locale_fk` FOREIGN KEY (`locale`) REFERENCES `craft_locales` (`locale`) ON DELETE CASCADE ON UPDATE CASCADE). The SQL statement executed was: INSERT INTO `craft_sections_i18n` (`sectionId`, `locale`, `enabledByDefault`, `urlFormat`, `nestedUrlFormat`, `dateCreated`, `dateUpdated`, `uid`) VALUES (:row0_col0, :row0_col1, :row0_col2, :row0_col3, :row0_col4, :row0_col5, :row0_col6, :row0_col7). Bound with :row0_col0='7', :row0_col1=0, :row0_col2=1, :row0_col3='demo/{slug}', :row0_col4='{parent.uri}/{slug}', :row0_col5='2015-06-09 20:33:00', :row0_col6='2015-06-09 20:33:00', :row0_col7='864207ba-6e43-46cf-9fdb-3a72cda4c2df'`

I was basing my code loosely on this Stack Exchange question and answer, but for some reason I can't get structures to cooperate.

I think I'm not setting the locale properly.  Is there a better way to set the locale, or am I overlooking something else?

I haven't used locales before so i'm not entirely sure, but when I looked in the craft service that saves a section there is a bit that looks like:

foreach ($sectionLocales as $localeId => $sectionLocale)
...

Which I assume then means your array needs to look like this:

array(
 'en' => // model
)

Whereas yours was looking like this:

array(
 0 => // model
)

So craft was seeing 0 as the locale id and it was failing.

So I managed to get this to work by using the following code:

public function onBeforeInstall()
{
  // Get the current locales ID
  $currentLocale = craft()->locale->getId();

  $section = new SectionModel();
  $section->name = 'Demo';
  $section->handle = 'demo';
  $section->type = 'structure';
  $section->hasUrls = 1;
  $section->template = 'demo/page';
  $section->enableVersioning = 1;

  // Index the locales by their ID e.g en returns array
  $locales = craft()->sections->getSectionLocales(1, 'locale');

  // Target the locale we want by the key in the array
  $locales[$currentLocale]->urlFormat = 'demo/{slug}';
  $locales[$currentLocale]->nestedUrlFormat = '{parent.uri}/{slug}';

  $section->setLocales($locales);

  $response = craft()->sections->saveSection($section);
}

The Demo section was added and I got the 'IT WORKED' response, I hope that helps!

Edit

I suppose if you didn't want all the locales to be saved to a section you could just do something like:

$specificLocales = array();

// After setting the locale attributes
$specificLocales[$currentLocale] = $locales[$currentLocale];

$section->setLocales($specificLocales);


Download resource form page I am creating a resources page, on which a resource can be downloaded after filling or submitting a form. This form is having user info fields like first name, last name, email etc. Could anyone please suggest me how can I implement it in Craft.

It depends to some extent whether the form is a login/registration form (to a user account) or just an information form, that you are saving in the database.

If the resources page is restricted and requires login, then you should place {% requireLogin %} at the top of your resources template. If anyone requests this page they will automatically be redirected to the login page, and after a successful login, will be routed back to the original request, which was the resources page. The login page can have a link to 'create account' with the additional fields you need, if they don't already have one.

If it is just an information form and not for login then you can simply create a form with the required fields. Submit the form using action/saveEntry along with a hidden field called redirect as explained here.

<form method="post" action="" accept-charset="UTF-8">
    <input type="hidden" name="action" value="entries/saveEntry">
    <input type="hidden" name="redirect" value="path/to/resources">
    ...
</form>

This is not secure however. If you need to make certain that they just don't go straight to the resources page without filling out the form, then you can test for the existence of an entry.id on the resources page (which is what is returned from a successful entries/saveEntry), and redirect them back to the form again if not defined. However, this would make the resources page viewable only once (unless you set a cookie or store session data, etc). And they would have to fill out the form every time they wanted to view it, which doesn't sound like what you want. In which case go with the login route above.

There are example templates for login, user registration, and others (more links at bottom left of those pages).


Craft 3: Get missing translations Is there an easy way in Craft 3 to get all missing translations for a certain language after they were piped through the translate TWIG filter?

{{ 'translate this text' | t }}

There is a PhpStorm plugin that adds “Missing translations”, “Unused translations” and “Translation message correctness” inspections to the IDE.

https://github.com/kalessil/yii2inspections

But unless I am missing something, it’s currently missing support for “Missing translations” inspections in Twig files. Both other features work well with Twig:


Updated Information Requested | Craft CMS & MariaDB Is Craft stable atop MariaDB? The last update concerning MariaDB was October of 2014.

We currently have no open tickets or known issues with MariaDB.

Fun fact: according to our logs roughly 15% of Craft installs are running some version of MariaDB.


AWS EC2, Load Balancer and Updating Craft I have a pretty large Craft site that needs to be load balanced with multiple ec2 instances and one RDS mysql instance. Everything is working great, except for I noticed that if I get to the admin panel and run updates on craft/plugins. The site files only change on the ec2 instance i'm on.

Is there a way to update all my ec2 instances at once on update?

Thanks! Any help is appreciated.

Don't update Craft or any plugins on production.

Do the updates on a local/dev version of the site, commit the resulting changes, then deploy those to all of your EC2 instances with a CI/CD service like https://buddy.works or whatever your favorite service is.

Some related blog posts worth reading:

https://nystudio107.com/blog/database-asset-syncing-between-environments-in-craft-cms

https://nystudio107.com/blog/local-development-with-vagrant-homestead


Quick check to see if tag exists? Just wondered if there's a quick way to see if a specific tag exists from anywhere in the site (by ID)?

I'm creating a navigation bar, and need to include a specific tag... only if it has been created/used.

Cheers, Mark

This should get you going in the right direction: https://craftcms.com/guides/displaying-tags-that-are-in-use


Craft 2 JS error in CMS since upgrade to 2.7.0 My Control Panel has stopped working since upgrading to Craft v2.7.0. in chrome. I get the following JS error no matter what is clicked in the entry fields and no action is taken. So for example if I want to remove and image and click the minus button nothing happens. If I try and add Matrix fields nothing happens. All of these were working prior to the update.

  Uncaught TypeError: Cannot read property 'length' of null
      at n.constructor.getWorkingTaskInfo (cp.js:863)
      at n.constructor.setTaskInfo (cp.js:832)

I'm running on PHP 7.0.13 any ideas?

Try reinstalling Craft. I believe there was another report from a user that had similar JS errors. Try replacing the core Craft files in craft/app and see if that helps.

Craft 2.7.1 was also recently released.


How do I tell Craft not to automatically crop user profile images? When uploading user profile images, Craft forces you to crop it to a square. Is there a way to keep the images untouched instead?

You could add a custom asset field for the users' profile images and hide the default one in the CP.

Here's a plugin to do this: Control Panel CSS by Lindsey D


what is the correct way to programmatically set checkboxes (MultiOptionsFieldData) in a migration? (solved) I need to update existing entries after the creation of a checkbox fields, to apply the default value to everything that was created before the availability of the new field.
The code should run in a migration to be deployed along the changes in the project config.
What is the correct way to programmatically set checkboxes (craft\fields\data\MultiOptionsFieldData)?
I verified the migration updates the entry (the title for instance), but not the custom field:
$entries = \craft\elements\Entry::find()
  ->section('sectionProduct')
  ->all();

foreach($entries as $entry) {
  $options = $entry->distribution->getOptions();
  foreach($options as $opt) {
    $opt->selected = true;
  }
  $entry->distribution->setOptions($options);
  Craft::$app->getElements()->saveElement($entry);
}

After running the migration, the control panel never shows the checkboxes flagged (the checkbox field has two possible values).
TIA

Sleeping on it (and peeking at the db) provided a solution, with even simpler code:
$entries = \craft\elements\Entry::find()
  ->section('sectionProduct')
  ->all();

foreach($entries as $entry) {
  $entry->setFieldValue('distribution', ["1", "2"]);
  Craft::$app->getElements()->saveElement($entry);
}

where "1" and "2" are the values associated to the checkboxes.
If you know the checkbox values, use setFieldValue and pass them as an array:

[] (empty) no checkboxes selected
["single value"]
["multi", "values"]


Commerce: How to update an order status via the frontend Is there a way to edit an orders status via a frontend template?

A customer can not update the order status from the front end. Only a user in the CP with the right permissions can do so from the Edit Order page.
To add this functionality you would need to make your own controller action endpoint (in a plugin or module) that does the following:
<?php

namespace modules\mymodule\controllers;

use modules\mymodule\MyModule;

use Craft;
use craft\web\Controller;

/**
 * @author    You
 * @package   MyModule
 * @since     1.0.0
 */
class UpdateOrderStatusController extends Controller
{
    protected $allowAnonymous = ['index'];

    /**
     * @return mixed
     */
    public function actionIndex()
    {
        $this->requirePostRequest();
        $this->requireAcceptsJson()
        // validate the current user is allowed to edit the order?

        $newStatusId = Craft::$app->getRequest()->getRequiredParam('statusId');
        $message = Craft::$app->getRequest()->getRequiredParam('message');
        $orderNumber = Craft::$app->getRequest()->getRequiredParam('number');
        $order = Order::find()->number($orderNumber)->one();

        if($order){
          $order->orderStatusId = $newStatusId;
          $order->message = $message;
          Craft::$app->getElements()->saveElement($order, false);
          return $this->asJson([
              'errors' => $order->getErrors(),
              'success' => !$order->hasErrors(),
          ]);
        }

        return $this->asJson([
            'errors' => ['No order found'],
            'success' => false,
        ]);
    }
}


Order entries by date field I have a channel section with a handle named 'events'.

In my field layout for this section I have a field named eventsDate, which is a Date/Time field.

I also have a plain text field called 'eventsHeadline'.

What would be a good way to output the 'eventsHeadline' entries ordered by 'eventsDate'?

Read the article about ElementCriteriaModel in the official Craft docs on how to query elements in general and the craft.entries article about the parameter available to modify the object returned.

Example code for your events list:

{# Get events from `events` section in desired sort order #}
{% set allEvents = craft.entries.section('events').order('eventsDate desc') %}

{# Loop through `allEvents` and print the list #}
{% for event in allEvents %}
    <li>{{ event.eventsHeadline }} - {{ event.eventsDate|date('F j, Y') }}</li>
{% endfor %}


Is it possible to remove an entry's Expiration Date? Once I have given an entry an expiration date, is there any way to delete that date so that it never expires?

You could just empty the expiration date and time field and save the entry. Or do you want to do it in a plugin (using PHP)?


How can I route a specific entry in a structure section to its own template? While setting up a site recently I wanted to route a specific entry in a structure section to its own custom template. Using a dynamic route sounded like the right option until I remembered that it wouldn't work due to Craft's routing order (matched entry uri comes before matched template).

I considered adding a conditional redirect to the structure's generic template but this feels a bit dirty. Does anyone have a better solution of how to make this work?

The cleanest way I have found to achieve this is to create a generic template for the structure as well as a custom template for each entry that needs one, ensuring that its path matches the entry's uri.

I then put this single line of code in the structure's selected template and it works beautifully:

{% extends [entry.uri, '_generic'] %}

This should work as well:

{% include [entry.uri, '_generic'] %}

If the entry's uri exists as a template route then it will be rendered, otherwise the generic template will be.

UPDATE:

I recently extended this on a site to allow for unique custom pages, custom entry type pages and a fallback generic page:

{% extends [
    '_custom/' ~ entry.slug,
    '_entrytypes/' ~ entry.type,
    '_generic'
] %}


Craft Plugin Variable 'Undefined Index' I'm currently adapting a shipping plugin that has a form for people to submit their tracking number and shipping company.

The template checks the variable, and if it exists, it generates the proper information for the tracking number and company. If the variable doesn't exist, it shows the form.

basically this

if($ttr<>"") {
      All the business logic
} else {
    <form method="get">
        <input type="text" name="tracknum" />
        <select name="company" class="smallForm" id="company">
                (...options...)
        </select>
        <input type="submit"/>
        <input type="hidden" name="orderAction" value="track"/>
    </form>
}

The original check for this this variable looks like this

if (isset($_POST['tracknum']))
$ttr = $_POST['tracknum'];
else $ttr = $_GET['tracknum'];

So for I put each check in its own variable function, as so

public function ttr()
{
   if (isset($_POST['tracknum']))
       $ttr = $_POST['tracknum'];
   else $ttr = $_GET['tracknum'];
   return $ttr;
}

and call it thusly

{% if craft.PluginName.ttr|length %}
    All the business Logic
{% else %}
    <form method="get">
        <input type="text" name="tracknum" />
        <select name="company" class="smallForm" id="company">
                (...options...)
        </select>
        <input type="submit"/>
        <input type="hidden" name="orderAction" value="track"/>
    </form>
{% endif %}

This currently returns

Undefined index: tracknum

Specifically on the line

else $ttr = $_GET['tracknum'];

Now this makes sense to me, as the form hasn't been submitted, so There should be nothing in the $_POST or $_GET. But if that's the case, why does it work on the original website, but not here?

Thanks!

"... why does it work on the original website, but not here?"

Undefined index is a notice level PHP error. Which means it's barely important, and can generally be ignored.

This is probably a result of either:

Your PHP error level settings are more strict on this machine, and/or
Craft is in devMode on this machine.


Is it possible to combine information from two blocks from a matrix to an if function? I have a check box field called requiredPrograms, in it it has a selection of programs you can choose from. This is within a matrix field called Work shop Instructor which is for my workshop channel.

On my outside workshop page I'd like to display what programs are required for all the teachers at the workshop in the one spot. On the inner page they would be broken into separate programs per instructor.

I've done the inner page with no issue but I cannot figure out a way to do the outer one.

{% for block in entry.workshopInstructor[0] and entry.workshopInstructor[1] %}
   {% if block.requiredPrograms.contains('Photoshop')%}

Foo

   {% endif %}
{% endfor %}

That is my current attempt but this results in nothing being displayed and other attempts have only produced the output twice.

Any suggestions?

The question is a little unclear, is this what you are looking for?

{% set requiredProgram = false %}
{% for block in entry.workshopInstructor %}
   {% if block.requiredPrograms.contains('Photoshop')%}
      {% set requiredProgram = true %}
   {% endif %}
{% endfor %}

{% if requiredProgram %}
  Photoshop is enabled on one of this entry's blocks field.
{% endif %}


How do I pull an image from a child entry of a structure I have a structure, holding areas (level 1), and properties (level 2). I use entry types to pick what template will be used.

In my entry type 'area' template I'm listing the children of 'area' ('properties').
The children (entry type 'property', has an image field that I want to pull into my area template.

Here's the code:

{% set properties = entry.getChildren() %}
{% if properties | length %}

Properties

    {% for property in properties %}

{{property.title}}

    {% endfor %}

{% endif %}

This works, except I can't figure out how to pull the imageurl from the asset 'imageBackground' that sits in the entry type 'property' field layout.

Anyone?

property.imageBackground is an ElementCriteriaModel, which is to say that it always behaves much like an array of assets (even if you are sure there is only one).

So the short answer is that you need:

style="background-image: url({{ property.imageBackground.first.url }});"

The catch here is that this will fail if there is for some reason no such asset. This can happen even if the field is required, and so you should always check. There are several ways to check. This is straightforward:

{% if property.imageBackground|length %}
  {{ property.imageBackground.first.url }}
{% endif %}

Or you can use a loop:

{% for background in property.imageBackground %}
  {{ background.url }}
{% endfor %}

Or a default (this uses twig's ?: operator, and relies on some global image always being there, but you now only have one image to make certain is always there):

{% set background = property.imageBackground.first
   ?: g_config.defaultBackgroundImage.first
%}
{{ background.url }}


Unique carts for different users Is it possible to have a unique cart for different users? If I log in as a user and add items to my cart, and then log in as another user, it shows the same items in my cart. Can this be changed?

As you've found, Commerce carts exist independently of a Craft user's session.

A workaround would be to write a simple plugin that listens to something like the onLogin event and that plugin would check for the commerce_cart cookie and if it exists, nuke it.

That would force a new cart for each new login.


Omitting unused letters from A to Z list I'm displaying lists of members grouped by their surname initial which the user navigates using a list of letters from A to Z. This part was straightforward enough and the following code works to return all members with a particular initial.

{% set searchString = 'surname:' ~ searchLetter ~ '*' %}
{% set members = craft.entries.section('members').search(searchString).order('surname', 'firstName') %}

Where I'm struggling is listing only the letters for which there are members to use for navigation, or to be able to list them all but disable those that don't have members.

Currently I just loop over the characters in the alphabet and output all of them.

{% set characters = 'a'..'z' %}

If someone clicks on a letter that has no members they get a blank list, but this isn't ideal as it would be better if there wasn't a link to this page.

I know with SQL I could do something like a SELECT DISTINCT with grouping to return just a list of initials in use, but is this possible with Twig or would I need to look at writing a plugin?

[untested]

Something like this should do the trick:

{% for letter, members in craft.entries.section('members').order('surname', 'firstname') | group('surname|slice(0,1)') %}

{{ letter }}

    {% for member in members %}

{{ member.surname }}, {{ member, firstname }}

    {% endfor %}

{% endfor %}


Sprout Import: No Changes When Updating Entry I'm trying to update existing entries with Sprout Import but when I run the import even though there are no errors the entry's data is not updated. I simplified the JSON script as much as I could and it's still not working:

[
    {
    "@model": "barrelstrength\\sproutbase\\app\\import\\importers\\elements\\Entry",
    "related": {
      "relatedResources": {
          "@model": "barrelstrength\\sproutbase\\app\\import\\importers\\elements\\Entry",
          "params": {
              "slug": "test-import-child",
              "sectionId": 2
            }
        }
    },
    "settings": {
      "updateElement": {
        "params": {
          "slug": "test-import-parent",
          "sectionId": 2
        }
      }
    }
  }
]

I also tried doing it with just a plain text field instead of a relationship field and still didn't get any change.

[
  {
    "@model": "barrelstrength\\sproutbase\\app\\import\\importers\\elements\\Entry",
    "content": {
        "body": "Lorem ipsum dolor sit amet."
    },
    "settings": {
      "updateElement": {
        "params": {
          "slug": "test-import-parent",
          "sectionId": 2
        }
      }
    }
  }
]

Reasons why it is not updating

The fields data should be wrapped with fields.
If entry is on other site add siteId on params
E.g.

[
  {
    "@model": "barrelstrength\\sproutbase\\app\\import\\importers\\elements\\Entry",
    "content": {
      "title": "Test Import Parent",
      "fields": {
        "body": "Lorem ipsum dolor sit amet."
      }
    },
    "settings": {
      "updateElement": {
        "params": {
          "slug": "test-import-parent",
          "sectionId": 2,
          "siteId": 1
        }
      }
    }
  }
]


Output Placeholder, Max Length, Line Breaks, Initial Rows values for Fields in Sprout Forms I'm trying to create a dynamic form that loops through all the form fields and dynamically applies the HTML that matches the field type.

I can't seem to find what to use to output: Placeholder, Max Length, Line Breaks, Initial Rows.

Other values like field.type, field.required, field.handle work fine. But trying field.placeholder or field.settings.placeholder does not work.

{% set fields = tab.getFields() %}

{% for field in fields %}

    {% set required = field.required %}
    {% set field = field.getField() %}

    {% if field.type == "PlainText" %}
        <input type="text" name="fields[{{ field.handle }}]" value="{{ attribute(submittedEntry, field.handle) }}" placeholder="">
    {% endif %}

{% endfor %}

The problem is due you're trying to get a property from the FieldLayoutModel instead of FieldLayoutFieldModel please see the code bellow to fix the error.

{%- set layoutFields = tab.getFields() %}

    {% for layoutField in layoutFields -%}

        {%- set field     = layoutField.getField() -%}
        {{ field.settings.placeholder }}
    {% endfor %}


Match Matrix Fields Before Looping Through Results I hope someone has an example or something similar they have done in Craft before.  Her is what I have.

Structure:

Section -> Flight Company

Matrix Name -> Plane Details

Matrix Block: Plane Model and Part

Matrix Fields -> Model, Part (field type: Category)

I am needing to perform this match example (preferable in crafts.entries query)before looping through the records.

Example match needed:

Model = Cessna

Part = Propx45

I need to match both those conditions before looping through the results later on in the page.  I need to make sure all the Flight Company's match that criteria before outputing the Title of the Flight Company.

How best to accomplish this?

Updated Answer

Turns out the original answer only works if you've got an single instance of a Matrix Block on the entry.  If you have multiple, it will search through all of them and return results for any block that has any of the relations you're looking for, in spite of the inclusion of and.

As of the next post-3.0.9 release, you'll be able to get relational matches from individual Matrix Block instances using a method like so:

{% set targetModel = craft.categories.id(5).one() %}
{% set targetPart = craft.categories.id(20).one() %}

{# be sure and set the field ID of the Matrix field you're interested in here %}
{% set entryIds = craft.matrixBlocks.fieldId(55).relatedTo(['and',
        { targetElement: targetModel, field: 'model' },
        { targetElement: targetPart, field: 'part' },
    ])
    .select(['ownerId'])
    .distinct()
    .column()
%}

{% set entries = craft.entries.id(entryIds).all() %}

{# display the results #}
Total: {{ entries|length }}

    {% for entry in entries %}

{{ entry.title }}

    {% endfor %}

Original Answer
Assuming the setup in your question, something like this should work:

{# These are just two examples, but get the relevant target model and part categories however you want #}

{# resolve to the "Cessna" category #}
{% set targetModel = craft.categories.id(4).one() %}

{# resolve to the "Propx45" category #}
{% set targetPart = craft.categories.id(6).one() %}

{% set entries = craft.entries.section('flightCompany').relatedTo(['and',
    { targetElement: targetModel, field: 'planeDetails.model' },
    { targetElement: targetPart, field: 'planeDetails.part' },
]).all() %}

{# display the results #}
Total: {{ entries|length }}

    {% for entry in entries %}

{{ entry.title }}

    {% endfor %}

Here's the relevant "relations" part of the docs: https://docs.craftcms.com/v3/relations.html


hacksaw plugin - displaying first 100 characters I want to display first 100 characters from a rich text field.

I tried this:

{% set sumtext =  entry.bodyContent.type('text').first().text|hacksaw(chars='100', append='...') %}

But if there was a new paragraph in the first 100 characters and no full stop - both paragraphs are just joined together without a space.

I then tried:

{% set sumtext =  entry.bodyContent.type('text').first().text|hacksaw(allow='<p>', chars='100', append='...') %}

But the  gets displayed on the screen instead of the new line.

what is my best method to display the first 100 characters from a rich text field?

In my opinion, the first thing you should do is remove all HTML tags. It's not just paragraph tags which could cause you problems... what about <strong>, <a> or <img> tags which get cut off?

For legibility sake, let's also break this down into multiple steps:

{% set textBlock = entry.bodyContent.type('text').first() %}
{% set plainText = textBlock.text|striptags %}
{% set sumtext   = plainText|hacksaw(chars='100', append='...') %}

And finally, if you do want your text wrapped in a paragraph tag, just reapply that when you output it:

<p>{{ sumtext }}</p>

Since you mentioned having an issue with two paragraphs getting mushed together, let me address that too... You'll want to make use of the Craft replace filter, which can handle regex.

Couple of ways you could tackle that:

{% set plainText = plainText|replace('/\. */', '. ') %} (ensures periods are followed by a single space)
{% set textBlock = textBlock|replace('/<\/p> *<p>/', ' ') %} (gracefully combines paragraphs with a space in between)


How can I reload the Live Preview Iframe window using JS I tried to reload the iframe window using JS but haven't had any luck getting the lp-iframe iframe element, I was thinking I could do it using the Window.Craft object but not sure how?

setTimeout(()=>{
  var iframe = document.querySelector('.lp-iframe');
  iframe.contentWindow.location.reload();
}, 5000);

All you need to do is

Craft.livePreview.updateIframe(true);

to update the Live Preview iFrame


Check if cart contains valid products for discount code I am trying to setup some error trapping on the discount code to output an error message if there are no products that qualify for the discount code the user enters. Here is the code I have;

    {% set currentDiscount = craft.commerce.getDiscountByCode(cart.couponCode)%}

    {% for item in cart.lineItems %}
        {% set cartProductIds = item.purchasable.product.id %}

        {% if currentDiscount %}
            {% if not cartProductIds in currentDiscount.productIds %}You have no products in the cart that meet this discount{% endif %}
        {% endif %}
    {% endfor %}

Currently this doesn't give me anything back. Can anyone point me further in the right direction...?

Edit: I have since found the code I pasted as an answer no longer works or never fully worked. I am struggling to loop through an array and check against the other array and if no id's match then set an error. I want to check if any of the cart Id's match against any of the discount code id's.

Here is my revised code, but it just doesn't match fully. I don;t think it is a bug, but more likely a failing of my code. Can anyone shed any light?

{# THIS CHECKS THE DICOUNT CODE FOR IF THERE ARE ANY VALID/ELIGABLE PRODUCTS IN THE CART #}
        {% set currentDiscount = craft.commerce.getDiscountByCode(cart.couponCode) %}
        {% set codeError = null %}

        {% if currentDiscount %}
            {% set cartProductIds = [] %}
            {% set discountProductsIds = [] %}

            {% for item in cart.lineItems %}
                {% set cartProductIds = cartProductIds|merge([item.purchasable.product.id]) %}
            {% endfor %}

            {% set cartProductIds = cartProductIds|join('|') %}

            {% for product in currentDiscount.products %}
                {% set discountProductsIds = discountProductsIds|merge([product.id]) %}
            {% endfor %}

            {% set discountProductsIds = discountProductsIds|join('|') %}

            Products in Cart = {{cartProductIds}}
            Products in Discount = {{discountProductsIds}}

            {% if cartProductIds not in discountProductsIds %}
                {% set codeError = 'Sorry there are no products in your cart that are eligiable for the code ' ~ cart.couponCode %}
            {% endif %}

        {% endif %}

Try something like this:

{% set currentDiscount = craft.commerce.getDiscountByCode(cart.couponCode) %}

{% if currentDiscount %}

{% set cartProductIds = [] %}

{% for item in cart.lineItems %}
  {% set cartProductIds = cartProductIds|merge([item.purchasable.product.id]) %}
{% endfor %}

{% for product in currentDiscount.products %}
  {% if not product.id in cartProductIds %}{{ product.title }} not in cart.{% endif %}
{% endfor %}

{% endif %}


Using a user’s full name in the URL I like to have the user’s full name in their profile page-url rather than the username in case they don’t want their username associated with their full name. In my case they don’t get to set the username at the sign up point but might been asked for a username by the person signing them up.

So, how do i use the user’s full name as an identifier in the url of their profile page?

Like so: example.com/user/first-last

Is that even possible?

Marcus, I think you can use anything as an url for a user's page. In your case, I'd make a dynamic route like:

user/*

and assign it a template, for instance:

user/_entry

Within that template, all you'd have to do is lookup the user by the match found in the url. The variable matches contains the first-last part (the * part of your route). With that, the user should be easy to find:

{% set names = matches[1] | split('-') %}
{% set user = craft.users.firstName(names[0]).lastName(names[1]).first() %}

{% if user %}
    // Do with it what you want
{% endif %}

You'd have to be careful, however, that no two identical first- and last name combinations exists. The advantage of using the username is that it's always unique.


What's the most user friendly way to create a video block in a matrix field? I want to make it super easy for my user to embed a video from YouTube (maybe eventually from other sources) without having to get the iframe code. They should only have to enter the URL for the video, and maybe check a couple of optional settings, and the code will do the rest.

I'm planning to share the snippet and field architecture I develop here to save myself/others time in the future, but if someone else has already done this and wants to share first, even better!

From basic to robust:

Redactor has a plugin along that same vein but it's more basic—feed it a URL and it spits out the embed code in a Redactor field.

Craft-video-embed-utilty sounds like it might work as a basic option here. It's not a field type but a Twig filter that'll take the video URL the user enters (you could use it with any field, including a plain text field) and then spit out the necessary Twig embed code. If you want to build your own "options" from scratch, this could work.

Embedded Assets allows you to use embeddable media such as YouTube videos to your assets manager and spit out the embed code necessary.

Dukt's premium Videos plugin is probably the most robust option. It'll actually connect to YouTube or Vimeo, hooks into Craft's interface, and visually allow you to search for and embed videos. It includes a videos field type that matrix compatible.


Garnish - Event when selecting a category I have a "Categories" field in my section. I want to perform some JavaScript actions when a category is selected.

Is there any built-in event which will be triggered at that point?

Try something like this?

$("#fields-myCateogryField").data("elementSelect")
    .on("selectElements", function(e){console.log(e);})
    .on("removeElements", function(e){console.log(e);});


Slow Assets Listing in CP Our client has created a lot of folders and sub-folders to keep their assets organised. I would guess they've made around 700 to 800!! (Basically two folders for each post)

The assets page in the CP loads very slow now - is there anything I can do to speed this up?

The first step to diagnose would be to determine where the bottleneck is.

If you enable devMode, you'll see database profiling information in your browser's console, including the SQL executed for each query along with the total number of queries executed.

Those queries will be ordered by the slowest performing ones at the top.  If there are multiple, slow performing queries that are taking up the majority of the time it takes to load the page, then there is likely something we could do in Craft to optimize performance in your scenario and you should contact us at support@buildwithcraft.com and send along a database dump so we can try to reproduce.

If the database queries look like they are not the issue, then the next likely culprit is disc access times.  If these folders/files are in the cloud (S3, Rackspace, etc.), or you're using NFS for your file system, then those could be slowing down the request as well.


Limit search results for users by tag (and limit to 5 tags) I've read as many forum posts and documentation but am a little stumped over a specific use-case. Currently the search page grabs the url segment, loops through a verified user group, and uses the .shuffle() function to randomise order.

I'm looking to limit search results using relations with a customTagsField on a user's profile. It also needs to limit results using only the first 5 tags that the user has entered in customTagField, in the order they are arranged in control panel.

Search Results

    {% set query   = craft.request.getParam('q') %}
    {% set results = craft.users.group('verified').search(query) %}
    {% set users   = shuffle(results) %}

    {% if users|length %}

{{ users|length }} results:

        {% for user in users %}

{{ user.fullName }}

{{ user.intro }}

                            View counsellor

        {% endfor %}

    {% else %}

Your search for “{{ query }}” didn’t return any results.

    {% endif %}

I'm still a bit confused about relatedTo as well as source and target terminology, even though I've read quite a bit about it!

Is it as simple as changing results to:

{% set results = craft.users.group('verified').relatedTo(customTagsFieldHandle).search(query) %}

It doesn't seem possible to limit the tags searched using relatedTo (as you can with craft.tags, so I expect I'll have to edit the for loop somehow. I know about Twig's slice function but I'm not sure how to go about limiting by a user's tag entries.

Does anyone have suggestions for the optimal way to achieve this?

There’s no way to tell the relatedTo param to only factor in the first X relations per source element (the first 5 tags per user, in this case).

I can think of two ways you could accomplish this:

Option 1: Use two Specialism fields

Replace your “Specialism” Tags field with two Categories fields – “Primary Specialism” and “Secondary Specialism”. Limit “Primary” to 5 categories, so no one can ever enter more than 5 specialties in there, and they can list any additional specialties  in the “Secondary” field.

Then from your template, you can limit the search query to only factor in the “Primary” field:

{% set results = craft.users({
    group: 'verified',
    relatedTo: {
        targetElement: craft.categories({
            group: 'specialisms',
            search: query
        }),
        field: 'primarySpecialism'
    }
%}

This method will get more complicated if you do start allowing premium members to be found from both fields down the road; you would need to split it up into two separate user queries – first for the premium members, and then again for the normal members.

Option 2: Automatically store the searchable specialisms in a separate, hidden field

Install the excellent Preparse plugin, and create a new Preparse field called “Searchable Specialisms” with the following Twig code:

{% spaceless %}
    {% for tag in user.specialismTags.limit(5) %}
        {{ tag.title }}
    {% endfor %}
{% endspaceless %}

(Disable the “Show Field” setting so this field doesn’t show up on user profile pages. {% spaceless %} is required to remove initial whitespace character from the newly parsed “Searchable Specialisms” field)

Once the field is created, add it to your User field layout (Settings > Users > Fields) - doesn’t matter where.

Finally, update your set results template code to this:

{% set results = craft.users({
    group: 'verified',
    search: 'searchableSpecialisms:"' ~ query ~ '"'
}) %}

This approach will make it much easier to handle the premium member feature down the road, because you’ll just need to factor in whether they are a premium member or not in the Preparse field settings:

{% set limit = user.isInGroup('premium') ? null : 5 %}
{% for tag in user.specialismTags.limit(limit) %}
    {{ tag.title }}
{% endfor %}


How would I include the first category slug in the section's entry URL format? I have a custom section that uses routes like this:

/section/category/entry_url

In trying to program the search form results I realized that I need to explicitly define the entry URL format for the section so that the search results return the proper links to view the entries.

Currently I have /section/{category.slug}/{slug} but it is not working.

How would I set the entry URL format to include only the first category slug of the entry?

Thanks.

This got it working for me:

/section/{categoryFieldName.first.slug}/{slug}


How can I get the image picker on the WYSIWYG editor? I am running on the latest version of Craft (Craft CMS 2.6.3015).  I have a blog entry, which has a Rich Text editor for the body field.

However, I do not have an image or file upload field in the WYSIWYG editor, please see the screenshot below.

I have tried adding "image" to the array in /craft/config/redactor/Standard.json but it has no effect.

I have checked the storage folder and all folders have correct permissions.

Where is the button and how can I add it?

The simplest method would be to change your Redactor Config to Default in the rich text field settings. Should look something like this:


Updates for v3 are paid only? There was this "one time fee" mantra overall and now I read
https://craftcms.com/news/dot-all-2017-announcements

They will charge additionally on yearly base?
Does this include any update and security updates as well?

Ever since Craft 1 launched in 2013, purchasing a Craft license (Client or Pro editions) has included free updates – even major releases, which means that your current Craft 2 site will be eligible for a free upgrade to Craft 3 once it launches in April 2018.

With the release of Craft 3, this will change: in order for your site to stay updated, you'll have to renew your Client or Pro license yearly, for a reduced fee ($39/year for Client edition, $59/year for Pro). If you opt out of renewing after the first year, you won't receive any further updates, but your license will still be valid and your site will still work.

Note that the yearly fee does not apply to any existing licenses, which will continue to receive free updates indefinitely.

Source: https://craftcms.com/news/dot-all-2017-announcements


Editing entry in front-end I am trying to edit an entry automatically when you press a button. Is there a way to do this?

A bit more detail: I have listed up a few entries, each with their own button. When I press the button on a specific entry, I want the currentUser to be added to the User Field of that entry.

Currently I have managed to get this semi-working with a form where the user can edit the entry through input fields etc., changing their value, then submiting (as outlined under Entry Form in the docs). This is the prossess I want automated. When you press the button in the front-end the entry is edited with values set in the code and submitted.

Thanks!

Looks like you want to implement a feature to vote for entries. Have a look at these plugins, they make this really easy for you.

https://www.doublesecretagency.com/plugins/upvote
https://github.com/dukt/craft-like

If you want to implement something yourself, I would look into adding the button behavior using JavaScript, listen for click events and send the data over XMLHttpRequests to the entries/saveEntry controller.


Commerce Orders Search Bug in CP? I'm trying to figure out how searching for Commerce Orders in the CP works. I've run some tests searching against the following fields:

Shipping Business Name
Billing Business Name
Shipping Method

In all cases, searches seem to match nothing in these columns. For example, if the Shipping Business Name was "Acme" and I enter that in the CP search bar, I get no results.

Is this expected behaviour? That seems hard to believe if it is. How would a user filter down the list of Orders for a particular company or shipping method... or whatever?

We are working on providing better search for entries, products, orders,  and all other custom elements in Craft within Craft 3. For example we recently added the search keywords method to the element interface to allow searching on non core attributes or custom fields: https://github.com/craftcms/cms/commit/afffaa5dcdb0fc02b484192e42cd5c9d528db94a

The above additions like above will help us provide searching on attributes that aren't actual properties/getter methods on the order.

This of course doesn't help you in the short term when searching for orders on the attributes you listed. I have added it as a priority to see if we can somehow make searching on those attributes easier in Commerce 1.x

A temporary work around would be adding the information to the search index by creating some pre-parse custom fields: https://github.com/aelvan/Preparse-Field-Craft

For example you could create a pre-parse field called "businessShippingName" and add it to the order field layout. In the settings for that field, you could use the template: {{ commerce_order.shippingAddress.businessName }}. This would allow you to search based on the business shipping name, as well as list it more easily in the order index screen.


Trigger download after form submission I am working with a contact form plugin, written by an external developer several years ago. I want to trigger a file download upon successful completion of the form.

As it stands, I have an onPost event listener in a separate plugin which fires if the form data is valid and stored in the database correctly:

craft()->on('capture_submissions.onPost', array($this, 'triggerDownload'));

I have tried several things such as redirecting to a controller action:

$url = UrlHelper::getActionUrl('myplugin/whitepaper/download', array('id' => $id));
craft()->request->redirect($url);

Also tried to use sendFile:

craft()->request->sendFile($filepath, $file_contents);

This works, however I would like the page to refresh first, displaying a confirmation message and then to trigger the download. As it stands, the download is triggered but the page isn't reloaded so no success message and the form data is still displayed.

The way craft()->request->sendFile works, is that it responds to the HTTP(S) request by sending your file of choice to the browsers. As you can only return one answer to an HTTP request, you'd have to first redirect people to a confirmation page. On that page, you could have a download button, and use some Javascript to force the download to take place on page load or short thereafter. Don't leave the button out, as not everyone has JS enabled.


Get all images from a section I want to get all images from the section projekte which are bound to the asset field bild I then want to fiddle around with .limit() and maybe random filters.

So I grabbed all images like described here

This works but as soon as I add .limit()

{% set projectImg = craft.entries.section('projekte').find() %}
{% set projectImages = [] %}

{% for item in projectImg %}
  {% set currentImage = item.bild %}
  {% set projectImages = projectImages | merge(currentImage) %}
{% endfor %}

{% for asset in projectImages.limit(3) %}
   <img src="{{ asset.url }}">
{% endfor %}

This results in

  PHP Notice: Array to string conversion

Why can't I just ad whatever filter I want on that new loop now?

This is a misunderstanding of the difference between an ElementCriteria model and actual fetched elements.

Some useful background reading:

https://craftcms.com/docs/templating/elementcriteriamodel

What are the differences between an elementCriteriaModel and fetched elements?

You could do what you're looking for using Twig's random method:

{% set projectImg = craft.entries.section('projekte').find() %}
{% set projectImages = [] %}

{% for item in projectImg %}
    {% set currentImage = item.bild %}
    {% set projectImages = projectImages | merge(currentImage) %}
{% endfor %}

{# Grab 3 random images from the array #}
{% for counter in 0..2 %}
    {% set asset = random(projectImages) %}

    <img src="{{ asset.url }}">
{% endfor %}


Falling back to Parent Category if no asset exists I'm trying to make it so that if an entry image does not exist, then fall back to the category image that the entry belongs to. Right now this isn't working and is receiving an error.

{% set feature = entry.brandFeature.one() %}
{% set featureUrl = feature ? feature.url : entry.category.one().categoryImage.getUrl() %}
<div class="jumbotron category-jumbotron" style="background-image:url({{ featureUrl }})">

This is the error that craft is returning:

  Calling unknown method: craft\elements\db\AssetQuery::getUrl()

entry.brandFeature.one()

Is correct, you'll access the asset field and execute the one() function in order to fetch the asset.

entry.category.one()

Is correct too. You'll fetch the first category of your categories field

entry.category.one().categoryImage

Will access the categoryImage asset field of your category.

But then you do

categoryImage.getUrl()

So you try to get the url from the field value but you don't actually grab the asset that might be stored in the category.

categoryImage.one().getUrl()

However - keep in mind there could be entries without a category. Then you'll receive an error as well.


Image(r) transform and for loop I'm stuck with the .first() element and why the for-loop code won't work.

    {% set image = entry.bannerSlider.first() %}
    {% set transformedImage = craft.imager.transformImage(image,
      { width: 1420, height: 550, position: image.focalPoint,  effects: { grayscale: true, gamma: 1.5}, }) %}
    {% for image in entry.bannerSlider %}

    {% endfor %}

If I remove the .first() element the code breaks ("An unknown image object was used"), but, as this code populates a slider, I need all the images loaded, hence my attempt with the for-loop.

I think I am mixing up different Models, but need someone to point it out, please...

When using the for loop you don't need to set image as it is set in the for loop. You will also need to define transformedImage on every iteration, so move it within the for loop.

Give the below a go, it should do what you are after.

    {% for image in entry.bannerSlider %}
      {% set transformedImage = craft.imager.transformImage(image, { width: 1420, height: 550, position: image.focalPoint,  effects: { grayscale: true, gamma: 1.5}, }) %}

    {% endfor %}