You can use the relatedTo param on craft.tags like you can with any Element inside Craft.

All Elements inside Craft can be related to one another. There is a .relatedTo parameter available on all of the query elements like craft.entries and craft.tags.

You will need to pass a category object into this relatedTo parameter. I have included the group param below but this can be omitted if you want to query all of your tags.

{% set tags = craft.tags.group( 'groupName' ).relatedTo( category ) %}

More info on using Relations in Craft: https://craftcms.com/docs/relations

UPDATE

The relatedTo param takes one of the following:

An AssetFileModel, CategoryModel, EntryModel, UserModel, or TagModel
object
An element’s ID
An array of element objects and/or IDs

To get a CategoryModel using a slug inside your template you can use:

{% set category = craft.categories.slug( 'theslug' ).first() %}

This will set category to a CategoryModel which you can then use inside the .relatedTo param in the above example.

UPDATE 2

If you've set category to have their own URL's then category inside the template you've set to use is a CategoryModel.

You then set entries to all entries related to the category. Finally, use these entries to get all related tags.

{% set entries = craft.entries.relatedTo( category ).find() %}
{% set tags = craft.tags.relatedTo( entries ).find() %}


Somewhere in your templates, you're referencing a custom field competitionTitel that doesn't exist. It sounds like you might have recently deleted it.

It will probably look something like entry.competitionTitel in your template.  You either need to create that field or adjust your templates to not call it.


I believe a Reference Tag can not perform an image transform because it doesn't return an ElementCriteriaModel object.

I worked around this by using the craft asset id parameter:

    {% set assetSearch  = craft.assets.id(12651) %}

    {{assetSearch.first().getUrl('transform')}}


PSR-0 Composer Autoloading causing class not found in plugin

Problem was with how composer handles psr-0 and psr-4 autoloading, so by changing the composer.json like such, the classes were loaded.

{
  "autoload":{
    "psr-4": {"PluginX\\": "PluginX/"}
  },
  "require": {
    "andrefelipe/orchestrate-php": "0.14.0"
  }
}


Determine a layout based on column number

How about we have a matrix, with block types x and y. Then you can test for block type in your loop:

{% for block in entry.this %}
  {% switch block.type %}
  {% case 'x' %}
    ...
  {% case 'y' %}
    ...
  {% endswitch %}
{% endfor %}

Another issue is that 33.33 + 66.66 = 99.99, which is never going to be equal to 100. (Also, the test for equality is ==: {% if x + y == 100 %}). So let's use x = 1, and y = 2, for a maximum column width of 3. Here's the code:

{% set thisRowLength = 0 %}
{% set thisBlockLength = 0 %}

  {% for block in entry.this %}

    {# how long is this block? #}
    {% switch block.type %}
    {% case 'x' %}
      {% set thisBlockLength = 1 %}
    {% case 'y' %}
      {% set thisBlockLength = 2 %}
    {% endswitch %}

    {# start a new row if necessary #}
    {% if thisRowLength + thisBlockLength > 3 %}

      {% thisRowLength = 0 %}
    {% endif %}

    {# now we know it fits, output this block #}
    {{ block.content }}
    {% set thisRowLength = thisRowLength + thisBlockLength %}
  {% endfor %}

You will end up with an empty

 if there are no matrix blocks. If that will be a problem, test for it.


This sounds like that CalFileParser library you are using has some issues with timezones. There is a pull-request that supposedly fixes these, but I would rather exchange it for another library.

https://github.com/u01jmg3/ics-parser has the more modern codebase, seems to be actively maintained, more used, and can be installed using composer.


How can I ensure certain items always display at the end of a list?

How would you like to identify that particular entry? If you're happy to hardcode its id, then I'd do it like this with the filter filter and the without filter:
{% set allEntries = craft.entries.section('products').all() %}
{% set pcEntry = allEntries|filter(item => item.id = 1234) %}
{% set entriesWithoutPC = allEntries|without(pcEntry) %}

You can now output those however/wherever you like, e.g.

  {% for product in entriesWithoutPC %}

{{ product.title }}

  {% endfor %}

{{ pcEntry[0].title }}


If you want to add a default to an existing column in a table in a migration, you'd do something like this:

$this->alterColumn('tableName', 'columnName', array('column' => ColumnType::Number, 'default' => 0));

If you want to add a default to a new column in a table in a migration, you'd do something like this:

$this->addColumn('tableName', 'columnName', array('column' => ColumnType::Number, 'default' => 0));


Building my first Sprout Form and need ability to add Tags input

Short answer: yes it's possible. Longer answer: it will probably require some custom development during your implementation to get in place what you're looking for.

Sprout Forms has a Tags Field in the Relations Field section of the Form Builder. On the CP side, it's just a wrapper around Craft's Tag Relations field and will work the same way for Content Admins.

By default, this field just outputs a list of tags in a dropdown for a user to choose from.

But, does the field support submitting new tags? I don't know! As the Form is just receiving POST data I'd start by taking a look at how Craft's Tags field is sending new Tags when entries are saved in the back end and try to update the front end tag input to submit data in the same way and see if it works.

If it does work, the main problem here would then be that you'd like to update your front-end UI. You can do that using Form Template Overrides and override the input field for the Tags field to behave as you wish. As long as you are submitting the POST data in the same format, Sprout Forms doesn't care which field type you use or if you use javascript or a Vue Component to guide your user toward preparing the input for submission.

If it doesn't work, then we could consider that a Feature Request or you could address the problem by building out a custom Tags Field that behaves as you need it to using the Form Field API. You're more than welcome to use Sprout Form's Tags Field as a starting point.


Search through Linklist in Richtext field not working?

The reason that searching for Ascot doesn't match sponsorenhochdreiascot is because Craft doesn't do wildcard or fuzzy searching by default.

If you search for *ascot it would match.  You can all of the supported search syntaxes here: http://buildwithcraft.com/docs/searching

Update:
As of Craft 2.5, you can enable fuzzy searching by default.


How do I set all Assets fields in entry to same directory?

For long and complicated reasons, in order for this to work after Craft 2.5, your inner Asset field (the one that was restricting uploads to {folder.path}, will need to {folder.path|trim('/')} instead.


Allow users to change email address on front-end form

When I use my email field to attempt an email address change, I get a verification email generated by Craft sent to the new email address, but the email change is not reflected in either the CP or on the front-end when I refresh the form.

The user's email address won't actually update until you click the link in the verification email the user receives.


Check user is in User Group / Custom User Permissions

I believe what you're looking for is 'isInGroup'

{% if currentUser.isInGroup('groupHandle') %}

It will also accept an actual group object or a group ID as well.

There is also getGroups:

{{ currentUser.getGroups() }}

Will return an array of UserGroupModels all of the groups the user belongs to.

And finally, can:

{{ currentUser.can('permissionName') }}

Will check if the current user has the given permissions, whether that was indirectly assigned to them in a group, or directly assigned to them as a user.


Feed Me and Assets Field - Mapping Trouble

1.) Have you set the feed to update existing entries?
2.) Try to url-encode the URL in the JSON, it contains special chars like spaces.


You will have to accomplish this without pagination. This is a non-javascript way.

{% set page = craft.request.getParam('page') ? craft.request.getParam('page')|number_format : 1 %}
{% set batch = 3 %}
{% set limit = page * batch %}
{% set newPage = page + 1 %}

{% set items = craft.entries.section('projects').limit(limit) %}

{% for item in items %}

{{ item.title }}

    {# other markup for each item #}
{% endfor %}

More

This just increases the limit by the page number and the factor of BATCH while providing the next page number for the button url.


Image transform is turning my jpegs dark

Setting 'preserveImageColorProfiles' => true, in craft/config/general.php solved the problem.

https://craftcms.com/docs/config-settings#preserveImageColorProfiles

Note that you need to be running at least Craft 2.6.2778 for this config setting to work.


Merge list of categories related to 'project' entries - not working, a solution

Instead of using the Merge filter, I tried "Passing Multiple Relation Criteria" from the Craft Docs, replacing "and" with "or", below...
{# get all sticky Project entries #}
{% set stickyProjects = craft.entries().section('project').limit(30).sticky('1') %}
{% set stickyProjectEntries = stickyProjects.all() %}

{# get all non sticky Project entries #}
{% set projects = craft.entries().section('project').limit(30).sticky('0') %}
{% set projectEntries = projects.all() %}

{# Fetch, then merge, categories related to both sticky and non-sticky Projects #}
{% set stickyCategories = craft.categories()
    .relatedTo([
    'or',
    { sourceElement: stickyProjectEntries },
    { sourceElement: projectEntries },
    ])
    .all() %}

{% set usedCategories = stickyCategories %}

Which produced the desired result: (image)

Thanks all, I hope that helps you all.
:)


Try using replaceAssetFile(), something like this (untested):
$rename = Craft::$app->assets->replaceAssetFile($asset->id,$asset->getFolder(),$newFileName);


Use JavaScript to find the button and change the text. Fortunately, the Craft CP contains jQuery, so it should be fairly easy.

This plugin should help speed up the process... Your JavaScript will get loaded on every page of the control panel.

  https://github.com/lindseydiloreto/craft-cpjs


How can I base64-encode an Image Transform?

It's not going to work with this particular plugin:

        // Require an instance of `AssetFileModel`
        if (! $asset instanceof AssetFileModel)
        {
            // Die quietly.
            return false;
        }

It specifically checks the parameter that you pass in, and expects it to be an AssetFileModel. It wouldn't be too hard to modify the plugin to work for your use-case, though.

I see what you're trying to do; if you're using Craft 3, you could use the ImageOptimize plugin to do it for you.


How to show nothing when you leave an input field empty in the entries instead of showing an error?

Make sure to add an if statement to check if the value exist or not with the length filter for example.

{% if entry.videoPhoto50 | length %}
   <img src="{{ entry.videoPhoto50  .....
   ....
{% endif %}

So that your code is only executed if entry.videoPhoto50 has a value.


Is there a way to get the URL of the localised version of a product variant?

Try using this code:

{% set variantID = craft.request.getParam('variant') %}
{% set locales = craft.i18n.getSiteLocaleIds() %}

{% for locale in locales %}
    {% if variantID is defined %}
        {% set localisedEntryUrl = craft.commerce.variants.id(variantID).locale(locale).first %}
        {% if localeEntry.locale == locale %}
            {{ localisedEntryUrl.getUrl() }}
        {% endif %}
    {% endif %}
{% endfor %}


Have you tried to enter the database information in your .env file?

Your password is usually "root" in a MAMP environment.


In your Entry click on the revision list next to the entry title.


Migration to new server, left with default theme?

As written in the other comment. There were files from the fresh installation of Craft that I needed to delete. Once removed the template shown as intended.


How to find out which assets are being used

Create this function in your plugins variable:

public function getAllIds(){
    return craft()->db->createCommand()->select('id')->from('elements')->where([
        'not like', 'type', 'Asset'
    ])->queryColumn();
}

You'll fetch all ids in Craft, then you can to this:

{% set allIds = craft.your-plugin-handle.getAllIds() %}

{% set usedAssets = craft.assets({
    relatedTo: allIds,
    limit: null,
}).ids() %}

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

To be honest I'm not sure what the error is in your code. You should get all entries related to the asset, even if they are in a matrix block. Maybe you related to asset to a category and this category to an entry and you assume to get the entry(?)


Give Digital Download a try... it generates a masked URL for downloadable assets. You can restrict the download to a specific user or user group.

Disclaimer: I'm the plugin author.


I believe your problem lies in the parameter for user group. In Twig, you don't need the brackets if you're already in brackets. You just reference the variable and fields directly. So instead of:

{% set group = craft.users.group('{{ category.slug }}') %}

Try this:

{% set group = craft.users.group(category.slug) %}

You see, the ElementCriteriaModel that's parsing the parameter for group doesn't run all its function arguments through Twig. So you're confusing it by throwing braces in there. Just give it the variable and field without quotes or braces and it should work smashingly, provided that category.slug is the same as a group slug.


You would simply not wrap it in cache tags. I don't think there's anything like that EE function to specifically exclude parts within the tag. Might be worth a feature request though?

{% set item = craft.shortlist.item(entry.id) %}

{% cache globally using key "product-card-" ~ entry.id ~ "-1" until entry.dateUpdated %}

    {{ entry.title }}

    ...

{% endcache %}

// EXCLUDE THIS PART FROM CACHE
{% if item.inList %}

{% else %}

{% endif %}

{% cache globally using key "product-card-" ~ entry.id ~ "-2" until entry.dateUpdated %}

    ...

{% endcache %}


Getting Entry By Category for Landing Pages In A Structure

You need to find a way to get the right category model to be able to receive all entries related to it.
As you didn't set up our categories to have their own URL, you could find it using the relevant slug in your URL.
Assuming that maches your categories slugs:

{% set categorySlug = craft.request.getLastSegment() %}
{% set category = craft.categories.slug(categorySlug).first() %}

{% if category %}

    {% set entries = craft.entries.relatedTo(category).limit(12) %}
    {% for entry in entries %}
        {{ entry.title }}
    {% endfor %}

{% endif %}

Another, probably more elegant way would be to access a token set via a dynamic route:

'regions/[SLUG]' => 'regions/_index'

You would now be able to access that token from a variable "slug":

{% set category = craft.categories.slug(slug).first() %}


This isn't an issue with Craft, from the POV that the TTFB should be pretty consistent.  How are you testing it?

My guess would be that the issue is with your hosting. These two articles may help you:

The Craft {% cache %} Tag In-Depth

A Pretty Website Isn't Enough

Run some of the diagnostic tests listed in the second article.


How to create a border + border colour field on an image

It looks like you're using a Matrix block with a field inside a block called Image. Given that information, I'd add a new field to that block called Border. You could either use a colour field, or a dropdown to set your own values. Then maybe something like this on the front end:

{% if block.image|length %}
<img src="{{ block.image.one.url }}" {% if block.border|length %} class="bordered border-{{ block.border }}"{% endif %}>
{% endif %}

Craft doesn't have any relation to the front end of your site intrinsically, so you could call the field whatever you like.


Here's the regex I think you'll need:

\/teachings\/tag\/\d+\/(\w+)\/? → \/teachings\/topics\/$1
\/teachings\/series\/\d+\/(\w+)\/? → \/teachings\/series\/$1

A couple explanations:

\/ is an escaped / character
\d+ means one or more digit (0-9)
\w+ means one or more alphanumeric/underscore character (A-Z, a-z, 0-9, _)
surrounding something in parentheses makes it a capturing group, which can then be referenced when you're doing the "replace"

So in our regex we're matching the current url structures, capturing the slug, and then using that in the new url structures. Hopefully that helps!


Get "Internal Server Error Undefined index: handle"

This ended up being an environmental issue with semi-largish Matrix fields.

The three most common culprits are your php.ini file's max_input_vars, max_input_nesting_level and post_max_size would would need to be adjusted upwards, but other settings might come into play depending on your environment an Matrix configuration.

Also, if your server is running anything like mod_security or Suhosin, they have additional settings that might need to be adjusted higher that could affect this.


Variable "entry" does not exist in template at Structure Section

That entry variable will only be predefined for the template when you go to one of your entry’s URLs.

Your section’s Entry URL Format for top-level entries is {slug}, and your entry’s slug is qweasdzxc, so that would make your entry’s URL <site-url>/qweasdzxc (http://localhost/qweasdzxc).

If you change your section’s top-level Entry URL Format to reviews/{slug} instead of just {slug}, then the entry’s URL will become <site-url>/reviews/qweasdzxc.

When you go to <site-url>/reviews, you’re just accessing the reviews/index.twig template directly, so the entry variable was never defined, which is causing the error you’re getting.


Does this work?

{% redirect block.redirect.url %}

I don't know Linkit but this would be the correct twig syntax at least. For normal entry fields you would do

{% redirect block.redirect.one.url %}


Allowed memory size of 1610612736 bytes exhausted when updating via CLI on OS X

This ended up being a bug in Craft that was fixed in https://github.com/craftcms/cms/commit/df40f585cef3d7e47f811f73b08d9d71bbc9c9b2 and will be included in the next (3.3.14) release.


So if you have a variant attribute that is really a determining part of what the SKU actually is, you should probably consider use a dynamic title to build the variant title.

You can do this in the Product Type settings for that product type.  You do this by specifying a twig mini-template - here's an example:

There is also a twig mini template option for the variant's description to be built dynamically, and this is in fact what is shown for the line item in the order details in the control panel.  Here's another example:

This surfaces the information quite nicely:

In this case - the left side of the hyphen is the product's title, and to the right is the variant's title, which has been build dynamically from the paperSize attribute of the variant.


Adding users outside of CP or front-end registration form

You could write a custom plugin that exposed a anonymous controller endpoint that accepted to the user info you want to save.

From there the controller endpoint could create a new UserModel, populate necessary fields/properties you want to save, then call craft()->users->saveUser() and let Craft do the database populating.


Displaying gallery when viewing category page or entry with related categories - code review

Some "problems" I see with your solution:

You're repeating yourself twice there - it would be much better if you had your actionBilder loop in there only once. When writing code, try to use the DRY principle: Don't Repeat Yourself (obviously exceptions to that rule but this is one case where you could simplify).
Not sure why exactly you're using exists() to check you matrix block's presence. I've actually never seen that method in use before and had to look it up to see what exactly it does. Based on the docs, looks like you would use it to check if there are any related categories (but don’t need to fetch them). But like I said, I've never heard of exists() so could be I'm wrong... Fwiw, here's a great answer by Brandon Kelly on what you should use to check if a field is empty or non-existent.
This may not be a problem in your current setup but at the moment you're fetching three blocks from your matrix field and only displaying them if they are a particular type. This means if you were to ever add another block to your matrix you could end up with two, one, or even no images at all (because the three blocks you queried for are all of a different type). It would be better to grab three blocks of that particular type and then loop through them.

Here's what I'd recommend doing:

{# are we dealing with an entry page? #}
{% if entry is defined %}

    {# if so we create an array of related categories #}
    {% set categories = craft.categories.relatedTo(entry) %}

{# otherwise we'll check if this is a category page #}
{% elseif category is defined %}

    {# if so we create an array with our one category #}
    {% set categories = [ category ] %}

{% endif %}

{# make sure we actually have categories in the array #}
{% if categories | length %}

    {# start the `for` loop #}
    {% for category in categories %}

        {# does the matrix field exist and does it contain any blocks? #}
        {% if category.actionBilder | length %}

                {# get 3 `actionImg` blocks randomly #}
                {% for block in category.actionBilder.limit(3).type('actionImg').orderBy('RAND()').all() %}

                    {# get the block's first image's url #}

                {% endfor %}

        {% endif %}

    {% endfor %}

{% endif %}

Hope that's helpful!


Formatting Slug {postDate.month} to 2 characters

You should just be able to do:

postDate|date('m')

postDate by itself should give you a DateTime object which you can then apply the filter to.


How to catch errors in a service and return to a controller?

There are several ways you could go about this.

One that I tend to prefer is to go ahead and have your controller grab whatever data it needs from POST and populate a Model with it.

That model is what gets passed into your service layer.  Your service layer can run validation on the model (if any validation fails, you can retrieve the errors with $model->getErrors().

You can perform any additional custom logic and if any of that fails, use $model->addError() and return false.

Since the model will have been passed in by reference, your controller can see that false was returned and call $model->getErrors(), format those however you need and use $this->returnJson($myErrors) to send the errors back to the browser as JSON.


Getting the last X number of pages in pagination

As I already wrote in my comment 3 days ago something like this should work

{% paginate craft.entries.section('mySection').limit(10) as pageInfo, pageEntries %}

{% for page, url in pageInfo.getPrevUrls(3) %}
    {{ page }}
{% endfor %}

{{ pageInfo.currentPage }}

{% for page, url in pageInfo.getNextUrls(3) %}
    {{ page }}
{% endfor %}

{% if pageInfo.totalPages - pageInfo.currentPage > 3 %}
    ...

    {{pageInfo.totalPages}}
{% endif %}

[EDIT]: In the above script you will come across situations where the gap sometimes occurs between consecutive numbers, which can look silly.

To fix this you can add a little extra logic to it:

{% set amountVisible = amountVisible|default(2) %}
{% if pageInfo.currentPage > amountVisible + 1 %}
    1

    {% if pageInfo.currentPage == amountVisible + 3 %}
        2
    {% elseif pageInfo.currentPage > amountVisible + 3 %}
        ...
    {% endif %}
{% endif %}

{% for page, url in pageInfo.getPrevUrls(amountVisible) %}
    {{ page }}
{% endfor %}

{{ pageInfo.currentPage }}

{% for page, url in pageInfo.getNextUrls(amountVisible) %}
    {{ page }}
{% endfor %}

{% if pageInfo.totalPages - pageInfo.currentPage > amountVisible %}
    {% if pageInfo.totalPages - pageInfo.currentPage == amountVisible + 2 %}
        {{pageInfo.totalPages - 1}}
    {% elseif pageInfo.totalPages - pageInfo.currentPage > amountVisible + 1 %}
        ...
    {% endif %}

    {{pageInfo.totalPages}}
{% endif %}

Now this added logic will do two things:

If there is no gap, it won't render a thing.
If the gap only amounts to one page it will render a page number instead.

This results in the following:

As an added bonus: if you add the amountVisible variable on top with a default value you can put this in a twig partial which you can then easily implement on the paged view like so:

{% include 'partials/pager' with { pageInfo: pageInfo, amountVisible: 3 } %}

(Note that passing pageInfo explicitly is not required, but I do it for the sake of completeness and to prevent accidental cleanups of "unused" vars.)


Create web report able to be exported in pdf

This is a really broad question since it does not cover a specific topic but many things about plugin development. I would suggest you to read articles like So You Wanna Make a Craft 3 Plugin? or Enhancing a Craft CMS 3 Website with a Custom Module. You can create a boilerplate of a plugin with Pluginfactory.io.

To get used to the topic there are official documentations as well. If you have specific problem/question you can ask it.

In general there aren't many things that can't be accomplished with Craft. It's a really dynamic and flexible CMS and can be enhanced/extended in many ways.


You can certainly achieve a very rudimentary form of plural search by following the recommendations in AbbeyDesign's answer.

However, it comes with an important caveat: it won't work for plurals which do not include the singular form.

For example, baby / babies, knife / knives, or tooth / teeth.

If you need to accommodate this requirement, Craft's built-in search probably isn't going to cut it, and you'll need to go with something a bit more sophisticated.

I haven't personally tried it, but I think Search Plus can handle this. It's basically a convenient wrapper around Algolia, a very sophisticated search tool, which automatically handles pluralisation.


How do I dynamically define Asset Volumes' Base URLs for different Sites?

As happens, I had to "give up" and ask for help in order to figure out a solution myself.

My issue was I was trying to dynamically set @web and @webroot for the sake of Asset Volumes. That would presumably mess up other things that use those aliases.

A way to make it work is to create new aliases per-site for Asset Volumes. If someone else wants to do this, here is a way.

In config/general.php create aliases in the appropriate spot (e.g. in the * global, dev or whatever environment section you want) replacing <site-handle> with the handle of your site (set in the Settings > Sites panel):

'aliases' => [
  '@<site-handle>AssetsBaseUrl' => 'https://site-a.dev',
  '@<site-handle>AssetsBasePath' => '/Users/kirkroberts/Work/Codebases/site-a.com/online/public_html',
]

Now for the Asset Volumes for that particular site you can use @<site-handle>AssetsBaseUrl or @<site-handle>AssetsBaseUrl to start your Base URL and File System Path fields, respectively. (replacing <site-handle> with that Site's handle)

This should enable assets to be stored in whatever domain/folder you specify.

Of course, the aliases will need to be set manually for each environment in config/general.php, which is kind of a pain but not a huge deal.

Maybe that will help someone get it done or find an even better way to do it.


How do I display entries from multiple entry types?

You can set the ElementCriteriaModel's type parameter to multiple values by passing it an array of entry type slugs:

{% set teachers = craft.entries.section('teacher').type(['teacher', 'demoTeacher']) %}

Use the type property on the entry model to access its entry type in your conditional (also see this list for other available properties).

{% for teacher in teachers %}

    {{ teacher.title }}

    {% if teacher.type == 'demoTeacher' %}
        ...
    {% endif %}

{% endfor %}


How can I restore Matrix content after accidentally changing its field type?

As John mentioned, restoring a database backup is your best bet.

If you don’t have a recent backup, you may still be able to get your Matrix content back, thanks to semi-bug where Craft doesn’t actually delete Matrix block content, when a Matrix field is converted to something else.

Here’s what you can try:

Enable the Project Config file for your site, if you don’t already have it enabled.
Figure out what your field’s uid is by looking up its row in your database’s fields table.
Find the most recent project config backup in storage/config-backups/ where your field was still a Matrix field. The most recent backup will be called project.yaml, the second most recent will be called project.yaml.1, and so on. For each file, search for <field-uid>: (replace <field-uid> with the UID from step 2). If the nested type property is set to craft\fields\Matrix, you’ve found the right file. It will look something like this:

8823155c-e84a-4a38-af30-2cb88b705e7b:
  name: Body
  handle: body
  instructions: ''
  searchable: true
  translationMethod: none
  translationKeyFormat: null
  type: craft\fields\Matrix
  settings:
    maxBlocks: '3'
    localizeBlocks: false
    contentTable: '{{%matrixcontent_testimonials}}'
  fieldGroup: d58a1faa-0bf6-46b2-b880-b0c14bebca75
  contentColumnType: string

Find the same field definition in your current config/project.yaml file, and replace it with the field definition from the backup you found in step 3.
As a sanity check, you may want to compare the config backup from step 3 with the subsequent backup (so if you found your matrix field in project.yaml.10, compare it with project.yaml.9), using a diff tool like FileMerge (comes with macOS) or Kaleidoscope. If there are any other significant changes that happened at the same time, you may want to revert those changes as well in config/project.yaml.
Now access your Control Panel and click the button to sync your new project.yaml changes. When that’s done, if all goes well, your field should be a Matrix field again, and your content will be restored.


Element API throws 404 when not logged into CP

The issue ended up being related to the yii debug toolbar failing to execute correctly. Disabling it in app.php fixed it.


You can add a logo to the login page by uploading one to Settings → General Login Page Logo.
If you need further tweaking, you could use the Control Panel CSS plugin.
I wouldn't recommend modifying Craft's templates.


Sprig - Filter entries by custom field checkbox values, separate values as well as all values

My suggestion would be to give the Select All Values checkbox a unique name. That way, you can easily detect whether it was selected or not. You should also break dropdown_field out into 2 variables to avoid confusion.
{% set select_all_values = select_all_values ?? false

{% set dropdown_field_options = ['dropdown_value_1', 'dropdown_value_2', 'dropdown_value_3', 'dropdown_value_4', 'dropdown_value_5'] %}
{% set params = {section: 'section_1'} %}

{% if not select_all_values %}
    {% set params = params|merge({dropdown_field: dropdown_field} %}
{% endif %}

{% set entryQuery = craft.entries(params) %}

        <input sprig type="checkbox" name="select_all_values" id="dropdown_value_all" value="1" {{ select_all_values ? 'checked disabled' : '' }}>

            Select All Values

    {% for value in dropdown_field_options %}

        <input sprig type="checkbox" name="dropdown_field[]" id="{{ value }}" value="{{ value }}" {{ value in dropdown_field ? 'checked' : '' }}>

            {{ value }}

    {% endfor %}


So it should be:

{% set entries = block.teamGetEntres %}
 {% if entries | length %}
  {% for entry in entries %}

{{ entry.description }}

  {% endfor %}
{% endif %}

replace "entry" in entry.teamGetEntries with "block"


Pull Matrix Block from Multiple Entries without Showing Duplicates

Assuming you can have multiple person blocks per entry (group), you could:
Fetch your entries and eager-load the blocks and their entry to save some overheads
{% set group = craft
    .entries()
    .id([100,200,300])
    .with(['people.person:entry'])
    .all() %}

Then build an array with each person.entry
{# The array to store your person.entry #}
{% set people = [] %}

{# Iterate over your group #}
{% for entry in group %}

    {# Iterate over each blocks and push the person.entry to your people array #}

    {% for person in entry.people %}
        {% set people = people | merge ([person.entry[0]]) %}
    {% endfor %}
{% endfor %}

Then use unique (docs) to dedupe your people as you display:
{% for person in people | unique %}
    {{ person.title }} <br>
{% endfor %}


Tom, we applied the same technique to several clients. We also tried having one asset input and only allowing images and videos.  Then as we loop through the asset field we check for media type. However I think breaking it up like you have, is a better user experience so they know to add either video or image. We have also added a plain text field and allowed them to add Vimeo/YouTube embed code for the video.


Assign User to Group While Importing on Sprout Imports

Sprout Import for Craft 3 supports importing Users and assigning them to User Groups. See the Users page of documentation for more info.

To do so, you just need to assign the User Group ID to the groups attribute:

[
  {
    "@model": "barrelstrength\\sproutimport\\importers\\elements\\User",
    "attributes": {
      "username": "username",
      "firstName": "First",
      "lastName": "Last",
      "email": "user@website.com",
      "pending": 1,
      "lastLoginDate": "2014-12-11 04:12:06",
      "dateCreated": "2014-04-09 12:04:04",
      "dateUpdated": "2015-04-04 06:04:08",
      "admin": "1",
      "groups": [1,2]
    }
  }
]

LEGACY RESPONSE:

Sprout Import does not yet support importing to User Groups.

While we do hope to add this feature in the future, we currently don't have an ETA. Please feel free to reach out to us directly if you'd like to discuss custom development options to help get this feature implemented.

You can add comments to or follow this feature here.


How can I retrieve all the related entries?

This is more tricky then I first thought. I hope this is what you need:

In case the current entry element is not the source of your relation, find that source entry first. This entry then goes into the relatedTo parameter of a new ElementCriteriaModel, where we exclude the current entry entry using its ID.

Code is probably more easy to understand than my wobbling english explanation:

{{ entry.title }}

{{ entry.body }}

{# Get `allRelatedEntries` if this `entry` is the "source element" of the relation #}
{% set allRelatedEntries = craft.entries.relatedTo({ sourceElement: entry }) %}

{# Get `allRelatedEntries` if this `entry` is the "target element" of the relation #}
{% if not allRelatedEntries|length %}
    {% set sourceElement = craft.entries.relatedTo({ targetElement: entry }).first() %}

    {# Any relations at all? #}
    {% if sourceElement %}
        {% set targetElements = craft.entries.relatedTo({ sourceElement: sourceElement }).id('not ' ~ entry.id).find() %}
        {% if targetElements|length %}
            {% set allRelatedEntries = targetElements|merge([sourceElement]) %}
        {% endif %}
    {% endif %}

{% endif %}

{% if allRelatedEntries|length %}

Related Entries

        {% for relatedEntry in allRelatedEntries %}

{{ relatedEntry.title }}

        {% endfor %}

{% endif %}


Since Craft is mainly build for developers why don't you create your own plugin? From my experience Craft is a time saver all over the place and when you compare the time you need to build a complex non blog site with Craft and WP - Craft will win for sure unless you are going to build sites for less than 100$ with existing themes without writing a single line of code.

I don't know Yoast and I don't really know other SEO Plugins because we made a private real time analysis tool for our customers but I know even when we consider the time we spend for this plugin, all our sites consume less time and effort with Craft than with WP. With the experience I collected within the last 3 Years I can say it's not worth to use this CMS if you are going to solve every problem with an existing plugin like for WP.

Yii2 + Craft3 have awesome and very powerful tools to extend the system however you like. There are so many great features and opportunities to customize nearly every aspect of the system within a really short amount of time and effort without loosing much performance or risk security issues. Due to it's well considered API you can create complex frontend logic really fast with plugins and Yii modules.

If your director think the initial time loss is not worth it or if your company does not has the developers you need to create such a plugin it's not a good idea to move to Craft in the first place (at least that's my opinion) because as I said there are not that much plugins for Craft as there are for WP since it's so easy to solve problems and the group of customers is usually totally different

Edit:
within a quick search: maybe webtexttool is something you want?https://github.com/iNalgiev/webtexttool


need file extension in url to access template

The documentation for how Craft picks a template is here. Two of the relevant steps are:

  Is it an entry/category request?
  If the URI matches an entry’s or category’s URI, the section’s/category group’s template will get loaded, and the matched element will be made available to the template via a pre-populated entry or category variable.

and

  Does the URI match a template?
  Finally, Craft will see if the URI is a valid template path. If it is, it will return the matched template.

/about/our-people matches #4, and you get the about/_entry.html template. /about/our-people.html matches #6, so you get the about/our-people.html template.

The important thing is that Craft uses the first rule that matches.


This is Leslie, I'm the Chief Customer Officer for Craft CMS. I'm not sure I can help, but I'd like to know more. Specifically I'm not sure I can source a dev shop in Germany, but I may be able to get close. We do have Service Partners and we are privately testing a couple of service plans both directly from us and from contracting 3rd party shops that specialize in this type of support. Knowing more details will help us figure out how to develop this type of support from the community and directly from us. Please email me directly at Leslie@Craftcms.com.


First of all you should remove all "language" subfolders from your web directory because your web server will route directly in those instead of your default web/index.php. Craft will determinate the CurrentSite depending on your url not on the location of the file.

Second: make sure to insert an array with aliases in your config/general.php
I'll show a "complex" solution for multiple asset sources for multiple sites. If your site shares the same resources you'll just need the first array element but I want to show the concept

$publicPath = realpath(dirname(__DIR__) . '/web');
// ....
'aliases' => [
    'assetPath1'    => $publicPath . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR . 'folder1' . DIRECTORY_SEPARATOR,
    'assetPath2'    => $publicPath . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR . 'folder2' . DIRECTORY_SEPARATOR,
    //....
]

You should never access those files with

<script src="`{{ siteUrl }}/assets/folder1/jquery.js`">

Because this will use the current site url and append the structure. Therefore you have the alias function

<script src="`{{ alias('assetPath1') }}/assets/folder1/jquery.js`">

Now you can do some fancy stuff like

<script src="`{{ alias('assetPath' ~ currentSite.id) }}/assets/folder1/jquery.js`">

Or whatever identifier you like to access your asset files dynamically.


How to use Class Reference Classes within the Craft framework for plugin development

You may already be aware of this, but the Class Reference is a complete breakdown of the Craft core. Everything that exists within the craft/app folder is documented here.

Craft is built upon the Yii framework. If you dig deep enough, many roads lead back to Yii queries. Fortunately, you'll rarely have to dig that deep! Craft has abstracted away much of the raw Yii commands into all of its Base classes.

Continuing from there, pretty much everything else that happens in Craft is layered upon the Base classes. You'll notice that most of the common components (Services, Controllers, Records, etc) contain a Base class, and all other classes are extended from there. In general, you can think of the Craft core as being "one big plugin"... In fact, when Craft 3 is released, this will be even more true.

It's important to note that your plugin won't need all of these components. Many plugins require only a few of these components to meet their needs. In your case, you may only need a Service, a Controller, a Record, a Model, and a Variable.

Beyond that, I'll skip any recommendations for your specific plugin project. My intention was only to respond to the general purpose of your question... I'd highly recommend opening a separate question with specific points about what you are setting out to accomplish.


Category list not returning all related entries

How many categories do you have in that locations group? A criteria model returns the first 100 elements only by default, so any category falling behind that wouldn't be listed, no matter if there's related entries or not.

Add limit(null) to your craft.categories criteria model to make it return all categories.


Solution

This won't work in Twig as presented in the question (see why below). Instead, users would need to be changed to an associative array (or "hash" in Twig terminology) with keys that aren't integers, and you'd have to insert a merge inside a merge to change the value:

{% set users = {
    person0: {name: 'Bill', age: 25},
    person1: {name: 'Tim', age: 30},
    person2: {name: 'John', age: 32}
} %}

{% set users = users|merge({ person1: users.person1|merge({age: 1000}) }) %}

{% for key, user in users %}
    {{ key }}: {{ user.name }}, {{ user.age }}

{% endfor %}

...which now outputs:

person0: Bill, 25
person1: Tim, 1000
person2: John, 32

If you need to change the keys' integers dynamically, you will write it like this using Twig's attribute function and using brackets:

{% set loopIndex = 1 %}
{% set users = users|merge({ ('person' ~ loopIndex): attribute(users, 'person' ~ loopIndex)|merge({age: 1000}) }) %}

The Reason Why the Question's Array Doesn't Work

Twig's merge filter uses PHP's array_merge function, and according to PHP's docs when using array_merge:

  If the input arrays have the same string keys, then the later value for that key will overwrite the previous one. If, however, the arrays contain numeric keys, the later value will not overwrite the original value, but will be appended.

So trying to overwrite an existing hash in the original array

{% set users = [
    {name: 'Bill', age: 25},
    {name: 'Tim', age: 30},
    {name: 'John', age: 32}
] %}

...will just add the hash as a new, fourth item in the array, not replace the second one.  To demonstrate this clearer, we can rewrite users as a hash like this (it's considered the same as above):

{% set users = {
    0: {name: 'Bill', age: 25},
    1: {name: 'Tim', age: 30},
    2: {name: 'John', age: 32}
} %}

By trying to target the key 1 to change its hash and output users:

{% set users = users|merge([ users.1|merge({age: 1000}) ]) %}

{% for key, user in users %}
    {{ key }}: {{ user.name }}, {{ user.age }}

{% endfor %}

...we get this list:

0: Bill, 25
1: Tim, 30
2: John, 32
3: Tim, 1000

A new "Tim" user will get appended even if you make the keys strings like '0', '1', etc, or using Twig's attribute function. An issue for this was posted in Twig's github and the conversation explains it some more. You can only change a value if it's an array with a list of single values (not a hash) or if it's a key/value hash, and the key can't be an integer.


If only one Matrix block show this, for more then one block show that

Thanks to Brad for asking me a question above, it made me realize I was checking for matrix fields and not the matrix block. My code is now working that I am checking for the correct element on the page.

Revised code:

{% if entry.modelIds|length == 1 %}
     I am link - {{block.modelId}}

{% else %}
     Not a Link - {{block.modelId}}

{% endif %}

Thanks Brad for the help!


If you define your base site URLs using the siteUrl config setting (using the array syntax), then clicking the “Share” button should bring you to the appropriate locale’s URL.


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

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

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


Check out the Craft Entry Count plugin by Ben Croker...

  https://github.com/putyourlightson/craft-entry-count

Counting entry views is exactly what that plugin does.


How do I loop through two sections as one set

According to the Craft docs, the section parameter takes a "section handle, an array of section handles, or a SectionModel object". So this should work:

{% set entries = craft.entries.section(['press', 'in-the-press']).limit(10) %}

{% for entry in entries %}
    {{ entry.title }}
{% endfor %}


Conditional for user registration fields

Looks like I needed to set $user->username = craft()->request->getPost('email'); for my attempt to work.


Breaking one large Craft app into multiple smaller apps

The instances would all share the same database instance since we don't store any data in the database anyways so that wouldn't be an issue...

Brad or Brandon from P&T is probably going to chime in here with a better answer but it sounds like more trouble than it's worth.

For one thing, Craft relies on the database to determine if plugins are enabled or not. If your plugin is only "enabled" on one instance, the database is going to reflect that state. That sound likes a recipe for disaster.

Even if you make every piece self-contained, with multiple databases for each that "talk" to each via API like JSON or something else, you'll also have the problem of updating Craft's core files in multiple places whenever Craft itself gets updated. Multiple that by how many instances you have to determine what factor of headache you want...

Modularity is a good concept but it reads to me a bigger problem here is your deployment strategy and getting everyone on the same page as to what everyone should be working on, development wise. If one of your developers breaks the API for the other team that's calling it, you're just as screwed as before.

If your team is pushing up code that's broken, you want some way to revert back. That's true of any kind of system, modular or not. Small commits often. You might want to look at DeployBot or Capistrano or something else of that nature.


Get matrix entries related to an image asset via specific field

While you said that Attempt 1 was giving you the correct entries, just in the wrong order, if you have two blocks, you will probably find that you’re getting all blocks’ related entries each time. Because when you set that relatedTo param on block.entries, you’re actually overriding the existing relatedTo param that the Entries field type set, which limits entries to just those that are related to the current block. So with a little more testing you’ll find that’s more than just an ordering problem.

Attempt 2 is the right way to go - finding entries that are explicitly related to both the current block and some number of assets. If you want those entries to show up in the order they were related within the current block, you just need to set the order param. In this case you’ll want to set that to sources1.sortOrder, as sources1 is the alias that the craft_relations will get when it’s joined into the query to aid in a sourceElement relation param for the first time.

craft.entries({
    relatedTo: [
        'and',
        { sourceElement: block },
        { targetElement: craft.assets.kind('image'), field: 'pageImage' }
    ],
    order: 'sources1.sortOrder'
})

One thing I would recommend is, if you are going to be running this same query on multiple Matrix blocks on the same page, you should define that craft.assets ElementCriteriaModel outside of the main for-loop. That will save Craft a DB query for each block.

{% set allImages = craft.assets.kind('image').limit(null) %}

{% for block in entry.myMatrixField %}

    {% set entries = craft.entries({
        relatedTo: [
            'and',
            { sourceElement: block },
            { targetElement: allImages, field: 'pageImage' }
        ],
        order: 'sources1.sortOrder'
    }) %}

    ...

{% endfor %}


Get Commerce 2's Stripe subscription planData as object

A subscription's planData is currently only stored as JSON. You can use that JSON in your template but you'll need to decode it first. Marion Newlevant’s Twig Perversion plugin adds a json_decode filter among other helpful capabilities to Twig.

With that plugin installed, set planData to a variable with the json_decode filter applied to it then you can access attributes of planData as you normally would in Twig.

{% set plans = craft.commerce.getPlans().getAllPlans() %}
{% for plan in plans %}
    {% set planData = plan.planData|json_decode %}
    {{ planData.plan.amount }}
    {# Stripe stores the amount as cents, so formatting for dollars or euros might look like this #}
    {{ (planData.plan.amount / 100)|currency }}
    {# Trial period  #}
    {{ planData.plan.trial_period_days }}
{% endfor %}


Possible to append another field to entries field title?

Under the Section's entry type settings, you can uncheck the "Show the Title Field" checkbox and set the title format to be something like:

`{title} - v{myVersionFieldHandle}`


Fetch the three entries before, and after, a given Structure entry, with wrapping

Assuming that when you are on the first page, you don't show the last 3 entries of your structure and the single array you need is an array of entries, this should do it for you:

{# Set how many entries to have around current entry #}
{% set surroundingEntries = 3 %}

{# Fetch prev 3 entries - reverse order because of limit() #}
{% set prevEntries = craft.entries.positionedBefore(entry).orderBy('lft desc').limit(surroundingEntries).all() %}

{# Fetch next 3 entries #}
{% set nextEntries = craft.entries.positionedAfter(entry).limit(surroundingEntries).all() %}

{# if there aren't enough nextEntries, add some #}
{% if nextEntries|length < surroundingEntries %}
    {% set limit = surroundingEntries - nextEntries|length %}
    {% set extraEntries = craft.entries.section('sectionName').limit(limit).all() %}
    {% set nextEntries = nextEntries|merge(extraEntries) %}
{% endif %}

{# Put prevEntries back in order and merge nextEntries to it #}
{% set results = prevEntries | reverse | merge(nextEntries) %}

If you need an array of ids, replace .all() with .ids() and if I misunderstood you and  you need two separate arrays, simply don't merge them as results and use nextEntries / prevEntries but don't forget to |reverse your prevEntries to get them back in order :)


Unexpected output from Twig set variable

Try {{ social_image|default(social_image_fallback) }}. I've had good results using Twig's default filter over testing variables, even with multiple fallbacks. (like this).


Register front end member from admin area with password

Your best bet here is going to be to create a plugin.

One way that this could work would be to set up a plugin that defines a record for the front-end users, and then create one or more Control Panel pages for your Administrator to handle these records. Because the records can be defined any way you'd like, they can exist separately from Craft's baked-in User system.

This may actually be preferable in your case, since (if I'm understanding correctly) it sounds like you'd like to manage users logging into a separate frontend area, not the Craft admin Control Panel.

Regarding the Admin ability to manage User's passwords from the Control Panel, this feature was removed in build 2.3.2615. However, this answer does offer a way around this.


Undeleting entries (or restore previous version of deleted entry?)

In the toolbar above the element index you can use the "status" dropdown to filter by trashed elements. From there you can select the entries you want to recover and click the "Restore" button.


This is the correct way.
Examples:
Singles:
{% set entry = craft.entries.section('section_handle').one() %}

Channels / Structures:
{% set entry = craft.entries.section('section_handle').slug('my_slug').one() %}

General:
{% set entry = craft.entries.id(5).one() %}

See craft.entries for a list of all properties.


How to overwrite base controller beforeAction method

Solution is to create a custom controller in a module that extends the cart controller.
This gives the functionality to overwrite the beforeAction method, while keeping all other functionality.

As an example:

<?php

namespace modules\controllers;

use craft\commerce\controllers\CartController;

class FooController extends CartController
{
    public function beforeAction($action)
    {
        // Your overwritten logic here
        $something = 'test';

        return $something;
    }
}

Instead of posting to commerce/cart/update-cart you would then (in the example above) post to  my-module/foo/update-cart. There is some useful documentation in the Craft docs on building a custom module and how to create customer controllers and actions.

[Answered by Nathaniel Hammond Pixel & Tonic]


Plugin sending emails to all users in an entries Users field

If you have questions or other issues feel free to ask.
Please don't be confused, my Plugins handle/name is "Test" because I only use it for these purposes.. So whenever you see the name "Test" you know you have to rename it

This is your plugins init function

/**
 * Called after the plugin class is instantiated; do any one-time initialization here such as hooks and events:
 * @return mixed
 */
public function init()
{
    parent::init();
    craft()->on('entries.onBeforeSaveEntry', function(Event $event)
    {
        // trigger only when entries are changed not when created
        if(!$event->params['isNewEntry']){
            /** @var EntryModel $entry */
            $entry = $event->params['entry'];
            // create your logic to check if it is the correct entry...
            // you should check for your section here otherwise you'll send a mail for all updates^^
            // I just used the handle pages in my test system
            if($entry->getSection()->handle === "pages"){
                // next: fetch all user related to the entry...
                // since I don't know your entire fields, you have to implement the logic
                // to fetch users from entries that are related to the entry yourself
                // if you need help just ask
                $criteria = craft()->elements->getCriteria(ElementType::User);
                $criteria->relatedTo($entry);

                /** @var UserModel $user */
                foreach( $criteria as $user){
                    // create a new entry in the database
                    $email = new Test_EmailRecord();
                    $email->entryId = $entry->id;
                    $email->email = $user->email;
                    $email->save();
                }
            }
        }

    });
}

And you have to create the following record

namespace Craft;

class Test_EmailRecord extends BaseRecord
{
    public function getTableName()
    {
        return 'cron_mails';
    }

    protected function defineAttributes()
    {
        return array(
            // you could store the user Id here too, but this way
            // you can send the mail to non users too
            'email' => AttributeType::String,
            'entryId' => array(AttributeType::Number),
        );
    }

    // you could - if you want - create relations here..
    // https://craftcms.com/docs/plugins/records#defining-relations
    // but since it's only an example and not needed I skipped that part
}

And you need this in your controller

 /**
 * Cronjob to send emails... you can activate it every X hours
 * or once per day or whatever you want
 * when this function is trigger a specific number of mails will be send
 * their entries in the database will be deleted until there are no rows in the
 * table
 */
public function actionSendMails()
{
    // fetch mails with limit.. insert your limit here.. I would suggest to fetch 20-50
    // entries per trigger depending on how often it should run
    $emails = Test_EmailRecord::model()->findAllBySql('select * from craft_cron_mails LIMIT 1');

    if (is_array($emails) && count($emails)) {
        foreach ($emails as $email) {
            /** @var UserModel $user */
            $user = craft()->users->getUserByEmail($email->email);

            // do your logic if no user is found..
            // of course you could store the user Id rather than the email in the database table
            // but this way you can send the mail to non users too if you like
            if (!$user) {
                // you can just remove that part
                // I just wanted to show you could create an array with defaults here
                // if the user is not registered
                $user = array(/* fill some placeholders for your twig template */);
            }

            // prepare templates, you can address each user personally with a hello Mr {{ user.name }}
            // the entry {{ entry.title }} was edited and such...
            $message = craft()->templates->render('path/to/template.twig', array(
                'user' => $user,
                'entry' => craft()->elements->getElementById($email->entryId)
            ));
            if ($this->sendMail($message, "The post was edited", $user->email)) {
                //remove the column if the mail was send
                $email->delete();
            }

        }
    }
}

/**
 * This function sends the mail, it usually belongs to a service
 * but to make it easier I'll just leave it here
 *
 * @param $message
 * @param $subject
 * @param null $mail
 * @return bool
 */
public function sendMail($message, $subject, $mail = null)
{
    $errors = false;
    $adminEmail = craft()->systemSettings->getSetting('email', 'emailAddress');

    $email = new EmailModel();

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

    if (!craft()->email->sendEmail($email)) {
        $errors = true;
    }

    return $errors;
}


Ugly Redactor II and how to fix it with some CSS

Here is my eye-friendly code:

/* Redactor|Fonts */
[class^="redactor-"], [id^="redactor-"] {
    font-family: inherit !important;
}

/* Redactor|Toolbar */
ul.redactor-toolbar a {
    padding: 12px 13px !important;
    height: auto !important;
}
div.redactor-dropdown, ul.redactor-dropdown {
    font-size: 13px !important;
}
a.redactor-dropdown-h3 {
    font-size: 18px !important;
}

/* Redactor|Tooltip */
span.re-button-tooltip {
    z-index: 1 !important;
    bottom: -18px !important;
    background: none !important;
    color: #333f4d !important;
    font-size: 10px !important;
}

/* Redactor|WYSIWYG-Editor */
div.redactor-layer {
    padding: 20px !important;
    font-size: 15px !important;
    line-height: 22px !important;
}
div.redactor-layer h3 {
    font-size: 20px !important;
}

/* Redactor|HTML-Editor */
div.redactor-box textarea.open {
    padding: 20px !important;
    border-top: 1px solid #e3e5e8 !important;
    border-left: none !important;
    border-right: none !important;
    border-bottom: none !important;
    background-color: #333f4d !important;
    color: #fff !important;
    font-size: 12px !important;
    line-height: 18px !important;
}

Just paste it into the Control Panel CSS plugin.


Display entries that meet multiple tag params

Ideally, you'll use a dynamic route that can match any number of tags – negating the need to hard code the number of possible tag segments.

You can't pull this off using the Routes admin inside the CP, so crack open your /craft/config/routes.php file and add this:

return array(
    'tags/(.+)' => 'path_to_your_tags_template',
);

The above route can have any number of segments under /tags, but will require at least one. Be sure to delete any conflicting routes defined in Settings -> Routes!

Inside your tags template, you can get an array of all the tags in the URI like this (the |slice(1) part removes the first segment, i.e. "tags"):

{% set tagSegments = craft.request.segments|slice(1) %}

To pull the actual tags, you can do something like this:

{% set tags = craft.tags.slug(tagSegments) %}

Pulling it all together, here's how a (simplified) version of your template could look:

{# Get tags #}
{% set tagSegments = craft.request.segments|slice(1) %}
{% set tags = craft.tags.slug(tagSegments) %}

{# Get entries related to tags #}
{% set relatedTo = [] %}
{% for tagId in tags.ids() %}
    {% set relatedTo = relatedTo|merge([{
        targetElement: tagId,
        field: 'tags'
    }]) %}
{% endfor %}
{% if relatedTo|length > 1 %}
    {% set relatedTo = ['and']|merge(relatedTo) %}
{% endif %}
{% set entries = craft.entries.relatedTo(relatedTo) %}

{% if entries|length %}

Entries tagged with {% for tag in tags %}{{ tag.title }}{% if not loop.last %}{{ loop.revindex == 2 ? ' and' : ',' }}{% endif %}{% endfor %}

        {% for entry in entries %}

{{ entry.getLink() }}..

        {% endfor %}

{% else %}

No entries could be found with {{ tagSegments|length > 1 ? 'those tags' : 'that tag' }}.

{% endif %}


Conditional statement for nav tag when no children

Have you tried something like:

If that doesn't work, I suspect you could use {% ifchildren %} in concert with a variable to set the style. In this case, we set the variable to a non-null value if there are children. Then we can use the null-coalescing operator to substitute 'dropdown-item' if there are no children. Like:

{% set listclass = null %}
{% ifchildren %}
    {% set listclass = 'dropdown-submenu' %}
{% endifchildren% }


Thanks guys. I solved it.
The issue was that I was logging in as the admin not an ordinary user.


Use query string with relatedTo() with categories inside a category group

craft.categories will return you an object of type ElementCriteriaModel

craft.categories.slug('what-we-do/' ~ category|default) sets an attribute of this object, but it does not fetch the elements yet.

The relatedTo parameter needs to be an element, a list of elements, an array and some other staff but it can't handle a query (which the ElementCriteriaModel is)

You have to fetch the element(s) before you pass it to the function with first(), ids(), last() or find()

craft.entries.section(sections).relatedTo(craft.categories.slug('what-we-do/' ~ category|default).first())

Btw: just as an additional note {{ cat | kebab }} will print the title in kebab case. Mostly that will be the slug but if the user changes the title or the slug or inserts something completely different from the beginning, your logic will break


That bootstrap file is only meant to be used by web applications. Even if you got past this error, the file is still going to give you a WebApp instance, when what you really want to be working with in that environment is a ConsoleApp.

If you want to load Craft from the command line, use craft/app/etc/console/yiic instead (make sure it has executable permissions), or if you already have a PHP script running, load yiic.php.

Unfortunately those files don’t work like bootstrap.php though - they will not only instantiate a ConsoleApp instance, they’ll run it as well. So you would need to provide your own functionality through a plugin that adds custom console commands. You would do that by creating a consolecommands folder in your plugin folder, with files inside it that end with Command.php (e.g. MyPlugin_UtilsCommand.php) and a matching class name, which extends BaseCommand.

More details about how to write the class are available from BaseCommand’s class reference.


Painfully slow Feed Me import of User accounts

Turns out the answer in my case is to use a JSON data source.

Importing users as .json instead of .csv appears to be about 10 times faster:

With .csv importing 480 users took 2.5 hours
With .json importing 455 users took 15 minutes

My JSON looked like this:

{"user": [
    {
        "username":"jane.doe@example.com",
        "email":"jane.doe@example.com",
        "firstName":"Jane",
        "lastName":"Doe",
        "password":"User pass phrase",
        "groupName":"User group name"
    },
    {
        "username":"joe.bloggs@example.com",
        "email":"joe.bloggs@example.com",
        "firstName":"Joe",
        "lastName":"Bloggs",
        "password":"User pass phrase",
        "groupName":"User group name"
    }
]}


Building a website containing restaurant menus from multiple vendors -- need some advice on Section hierarchy of data

Ok, just spitballing here, but this is where my brain is going...

Channel: Restaurants

Each restaurant is a unique entity, correct? So they wouldn't need to be in any specific order, nor nested. (Chain restaurants could be related by other means.) All of your broad restaurant-based fields would be here, including location, phone number, hours of operation, etc.

Channel: Menu

I feel the menu should be a separate channel from the parent restaurants for a couple of reasons:

Seasonal/specialty menus: One restaurant, many menus.
Chain restaurants would share a menu: Many restaurants, one menu.

Within your Restaurants channel, create an Entries field (with a limit of 1) called "Menu". So each restaurant could select its current menu.

Matrix: Menu Items

Within your Menu channel, you'd have a Menu Options matrix field. Each menu option would be its own matrix block.

If you want to use the built-in category system, you may be able to create Category Groups based on different restaurant genres (Mexican, Thai, etc). You could then simply use those very broadly. However, I'd be concerned that those broad categories don't properly address the needs of each individual restaurant.

Alternatively, you may end up needing to create faux categories... I'm not sure you could get the normal category system to work for you here. There would be such wide-ranging variations between the categories of different restaurants, it would be a nightmare to keep up with that using the standard categorization options.

Faux Categories

You could potentially create a dropdown menu to represent your "categories" for a particular restaurant. That faux categories menu could be driven by the amazingly powerful LJ Dynamic Fields plugin. Might take a little trial & error, but that plugin will allow you to build a dropdown menu to be exactly as you need it.

With this method, you could allow each Menu to have its own definition of categories. Create a table field called "Categories" in your Menu section, and allow LJ Dynamic Fields to take advantage of that.

eCommerce Options

I can see why you'd gravitate towards making each menu item into its own entry, but I don't believe that's necessary. Take a look at some of the more generic, non-Craft options for building your checkout process. Specifically Snipcart and Foxycart allow you to render a product however you want to, and don't restrict your back-end data to any particular architecture.

My instinct is telling me that your menu options would be much better suited as a matrix field (or even table field), rather than being their own entries.

Hope that helps, even if it just gives you some new ideas to kick around! :)


Why are some entry detail views empty in the control panel?

That error isn't a Craft or PHP error, it's coming from older versions of xDebug.

It can happen on more complicated pages (lots of fields, tabs, etc.), but you can get around it by adjusting the xdebug.max_nesting_level to something higher than the default 100 or to upgrade xDebug to 2.3+, which has changed to the default value to 256.

Note that you don't have to have an active debug session going on in order to run into this, you just have to have the xDebug extension installed.


How can I check if a plugin is installed and enabled?

On top of checking within the admin area, there are some other ways you can do this, both in templates and in your plugins.

In a template

{# Second argument is if you want enabled only #}
{% set plugin = craft.plugins.getPlugin('pluginHandle', false) %}

{# Now you have access to these methods... #}
{{ plugin.isEnabled() }}
{{ plugin.isInstalled() }}

For a full list of methods, see PluginVariable in craft docs.

For more info on how to get plugins within your templates, see the PluginsVariable, note this is different from PluginVariable.

In your plugin

To check a plugin from within your own plugin:

// Again, second arg is if you just want enabled plugins
$plugin = craft()->plugins->getPlugin('pluginHandle', false);

// Then you can do things like:
$plugin->isInstalled
$plugin->isEnabled;

See the PluginService and also the BasePlugin for more info.

Hope that helps :)


User Registration Form with Sprout Forms

You don't need to use Sprout Forms to create users on your website. Take a look at the Craft documentation for an example.


I'd just crop it with CSS, as you alluded to. https://www.webpagefx.com/blog/web-design/circular-images-css/


Show a list of pages but hide the current page from the list

To me it looks like the entries in the section with the handle pages have their own URLs. This means that if you visit a URL that belongs to an entry in that section Craft will automatically make that entry available in the template as the entry variable. That being said your solution is in this case:

{% set currentPageId = entry.id %}
{% set pages = craft.entries.section('pages').id('not ' ~ currentPageId).all() %}

        {% for page in pages %}

{{ page.getLink() }}

        {% endfor %}

Or as an alternative:

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

        {% for page in pages if page.id != entry.id %}

{{ page.getLink() }}

        {% endfor %}

Here is a read about how Twig handles variable scope if you ask yourself why the entry variable is available in the included template:
https://nystudio107.com/blog/twig-processing-order-and-scope

Also, here is a link to Twig's docs on conditional for loops: https://twig.symfony.com/doc/2.x/tags/for.html#adding-a-condition


Output coupon in the code back end using Craft Commerce

I have gone ahead and made the coupon used more visible on the order edit screen. Will be in the next release of Craft Commerce.

In the meantime, if you want the code to show up in the discount description in the backend, add it to the discount description when setting up the discount.


Visitor array has empty values with Smart Map plugin (using MaxMind)

Was using the MaxMind free trial and I didn't have the Web Service set correctly in the Smart Map plugin settings. It needed to be set to GeoIP2 City.


Plugin RegisterUrlRulesEvent - cannot find Controller aciton -> 404

Found a Solution
Context:
When I created my plugin-frame through https://pluginfactory.io the DefaultController was still a thing -> routing to /pluginname/default-controller-action-name worked as it defaulted to search in the... default-controller. But it seems that is no more, so what I had to do instead to get it to find the action is add a section referring to the controller.
this is the new/fixed code:
// ./src/Expedweather.php::init
$map_page = 'data\/<range:\w+>\/<peak:\w+>\/<view:\w+>\/<parameter:\w+>';
$event->rules[$map_page] = 'expedweather/default/forecast-panel'; // <-- changed!!
// ./src/controllers/DefaultController
protected $allowAnonymous = ['index', 'forecast-panel'];
public function actionForecastPanel() {...}

The only row that changed is the $event->rules one which now has /default/ before the action -> this refers to the DefaultController.


Craft Commerce stock not updated when order deleted

Definitely deliberate.  Inventory reduction when an order is placed is a "convenience" thing.

There are a million reasons why an order might be deleted and only a handful of them would have anything to do with inventory.

But as André points out... you could write a simple plugin to have whatever behavior you wanted around this.


Uploaded Assets always get 600 File Permission and are therefore not displayed (403 Error)

I just missed the "Assets in this volume have public URLs" lightswitch while setting up the volume :)


If the craftcms folder is more or less the out-of-the-box Craft 3 installation, you should be able to just point your Directory blocks and DocumentRoot at /var/www/html/craftcms/web!

Only the web folder is intended to be public—everything else should be hidden, above the web root—think of it as sandboxing access to just one folder of your application.


Is there a masked input field type for Craft?

I just wrote one! MN Match Input. You specify an Input Mask and the entry won't save if preg_match($inputMask, $value) isn't 1. So you get all the power of preg_match (lots of rope...)


Calling a plugin function after an entry is deleted?

You can create a simple plugin that listens to the onDeleteEntry event.

There is an entry parameter passed into that event that is the EntryModel object that represents the entry that was just deleted.


What is the correct method for getting a client to purchase a Craft license?

I normally pay for the license and bill back to the client, turning off automatic renewal. After purchasing, if the client wants to have access to their license, I have them create a Craft ID account and transfer the license to them.


Display entries that belong to a category

Categories are Craft's implementation of a taxonomy, which itself is the classification of things into groups and sub-groups. In this respect, I suppose it makes sense that if an entry is related to a sub-category, it inherits (it's also related to) its parent. That would explain why you're getting all entries in this way.

At the moment, the only way I can think of is to test what level the category/sub-category is.

Something like this would get you started for the time being. I don't really like this because it seems convoluted, so I'll put my thinking cap on and I may revise.

{% set category = craft.categories.group('myGroup').title('1.').first() %}
{% set entries = craft.entries.section('mySection').relatedTo(category).find() %}
{% set isThisLevel = false %}
{% for entry in entries %}

    {# Test if this entry is related to the correct category level #}
    {% for relatedCat in entry.catField %}
        {% if relatedCat.level == category.level %}
            {% set isThisLevel = true %}
        {% endif %}
    {% endfor %}

    {# Only output if it's this category level #}
    {% if isThisLevel %}
        {# Do whatever you want #}
    {% endif %}

{% endfor %}


You can get all product types within your templates with:

{% for productType in craft.commerce.productTypes %}
  {{ productType.name }}<br>
{% endfor %}

There is no way to get a specific product type within templates at the moment, but I have added to the list. In the meantime you would need to look over all and find the one you want as above.


"Measure twice, cut once" goes the saying... (Kind of the opposite here, but the same principle!) - Fetch your data once, then cut it up how you like using Twig filters. In your case you can fetch the first item from an array with [0] and then slice off that same entry from the start of the same array with |slice(1) like this:
{% paginate craft.entries.section('blog').order('postDate desc').limit(13) as entriesOnPage %}

{% set firstEntry = entriesOnPage[0] %}
{% set theRest = entriesOnPage|slice(1) %}

{# ======================================================================= #}

{{ firstEntry.title }}

{% for entry in theRest %}
    {# OUTPUT 12 Entries not including the first #}

{{ entry.title }}

{% endfor %}


Is it possible to have multiple locales that use different domains instead of subfolders?

It is discussed here in the craft docs:

There is an example with different toplevel domains.

English and German each get their own domain

craft/
public_html/            --> example.com/
    .htaccess
    index.php
public_de/              --> example.de/
    .htaccess
    index.php


Exclude path in NGINX config (for FastCGI Caching)

I've tried doing this with headers and cookies, but haven't had any luck yet. What I think is happening is that these things are set after the request is made.

You are correct. fastcgi_cache is basically a switch, is it on or off. Your backend has no say in that because nginx doesn't look to the backend at all to figure out whether it should serve the request via cache or fire up FPM. It looks via the things it does have access to at the time... location, query_string, user_agent, etc.

How often does your client need to update?

One of the things that makes nginx fast is config files are only read into memory once. Apache, by contrast, looks for .htaccess files inside every directory in the tree on every request being served.

To make changes to a config requires nginx to be reloaded (or restarted). Complicating things, port 80 is a privileged port which means to open it up/listen on it, you need to have root permissions. That's not something you would want to give to a user via a web interface.

However, there are some workarounds.

If you are able to name your slugs differently in advance (e.g. append or prefix "-form" or "-dyn" or something like that to the URL), you can use that to tell nginx not to load from cache.  You could even have Craft generate part of the URL for you based on the value of a "Does this have dynamic content?" lightswitch.
Generate part of the nginx config dynamically by using a cron job which runs a shell script every 15 mins or so to check if there are configuration changes. If there are changes, reload nginx. I'd recommend using a map, put that in a separate file, and then include it so you're not touching of the main config files.
Use the lua module. Lua is a scripting language that lets you run dynamic code on every request. I haven't used it so I don't know how performant it would be but it could work to set variables, etc.
Load content in via JavaScript. Depending on what you're trying to do, ignore the web server altogether and load content dynamically. If it's an interactive thing that's going to be tough for google to cache anyway, that could work well here.

Caching is super tricky. Varnish has a lot more options when it comes to dynamic content but it's potentially another dameon you need to setup and maintain. nginx is great because of its simplicity, however, that simplicity comes at a cost of flexibility.


How can I implement advanced action routes (in routes.php)?

Yes it’s possible. First you will need to update your route key so that you’re capturing the name parameter with a valid named subpattern. (You were close, but missing the actual pattern part of it).

return array(
    'api/test/(?P<name>[^\/]+)' => ['action' => 'api/element/section'],
);

Any named subpattern matches in your route will be passed to your controller action’s $variables argument, if it has one.

class Api_ElementController extends BaseController
{
    // ...

    public function actionSection(array $variables = array())
    {
        $name = $variables['name'];

        // ...
    }
}

Note that you specifically need to call the argument “$variables”, and you need to typeset it to an array for this to work.


Help with an Entries field to an array I can use elsewhere

At the same time as you are iterating over your Hero posts, you could populate an array that you could then use in your most popular query.
This is just sudo code but hopefully you get the idea:
{# This would go before your hero loop #}
{# Initiate a heroIds array starting with not #}
{% set heroIds = ['not'] %}

{% for entry in heroEntries %}
    {# Add  heroEntries id to your heroIds array #}
    {% set heroIds = heroIds | merge([entry.id]) %}

    {# the rest of your code... #}
{% endfor %}

{# Then you can use this array in your most popular query #}
{% set entries = craft
    .entries()
    .section('news')
    .limit('4')
    .orderBy('popular')
    .id(heroIds)
    .all() %}


Reset admin account password using command line interface

There's not a native Craft console command that could do that, but plugins can supply there own console commands, so you can write a plugin that added a command to do so.

Craft 2 plugin docs: https://docs.craftcms.com/v2/plugins/introduction.html

Craft 3 plugin docs: https://docs.craftcms.com/v3/extend/plugin-guide.html

And you can generate plugin boilerplate for both versions here: https://pluginfactory.io/ and there's even a "Console Commands" checkbox you can tick.


Pretty sure PHP is interpreting that string as an int. Doing a var_dump on the variable shows int(596249628892364800). That's pretty much PHP's type casting at work.

While you could cast the variable as a string, there's actually an unused variable called id_str which is ideal to use.

Edit the file twitter\fieldtypes\Twitter_TweetFieldType.php. Replace line 48 from:

$url = 'https://twitter.com/'.$tweet['user']['screen_name'].'/status/'.$tweet['id'];

To:

$url = 'https://twitter.com/'.$tweet['user']['screen_name'].'/status/'.$tweet['id_str'];


Clean install - Service Unavailable message at setup

Had similar issues. Found the problem was in the .htaccess file.
Without code fixes, visit http://example.com/index.php/admin
instead of http://example.com/admin

Then fix your htaccess file later.


Do "update cart" and "complete cart" as one action

There's a few moving parts here but Commerce 3.3, which was recently released, just introduced support for partial or deferred payments which should help get this done easily.
I'm not sure what your checkout looks like but one way to handle it would be to post via ajax. Basically anything that updates on-the-fly (addresses, line items, etc.) needs to to get pushed to update-cart first.  You don't really need to write a plugin for this.
Then when you ready to complete the order, you could also make one final push to update cart. Then when a user wants to finalize, they then hit the commerce/cart/complete endpoint.
You could also have a separate "confirm your order" screen which could give the user time to check over their catering before it gets sent.
Either way, you want to have the new allowCheckoutWithoutPayment setting set to true.
It's also possible to grab a partial payment (say if your client wants to do a deposit).


Possible to set 2 data fields within 1 select option?

You could use the Preparse plugin to create a field that is automatically updated with the eventDate value whenever the entry is saved. It wouldn't be a datetime field, but if you stored the timestamp (i.e. {{ dateString|date('U') }}) it'd be easy to use as such.

Another option is to have an hidden input in your form for the eventDate datetime field, and use JavaScript to set its value whenever the <select> input changes (i.e. listen for the change event for the latter, in your JS).

The third option would be to write a plugin which listens to the entries.beforeSaveEntry event in order to set the eventDate value from the dropdown field.


How can I create a simple loop through entries in a category?

This example assumes you have your Category Group setup to use custom URLs.  In the template used to display your categories, the category variable will be available and represent your CategoryModel for that page.

The key is to pass the CategoryModel (in our example below category) to the relatedTo parameter of the Entries tag.

{{ category.title }}

{% paginate craft.entries
    .section('articles')
    .relatedTo(category)
    .limit(10)
    as entries
%}

    {% if entries|length %}

        {# Content #}
        {% for entry in entries %}
            {{ entry.title }}
        {% endfor %}

        {# Pagination #}

    {% else %}

No items have been added to this Category yet.

    {% endif %}

{% endpaginate %}


WYSIWYG removes HTML button all non- tags when view source

This is a feature of "redactor" which is used with Craft to clean and format input.

To change the settings, you need to change the config in Craft/config/redactor/. See http://buildwithcraft.com/docs/rich-text-fields and http://imperavi.com/redactor/docs/settings/clean/#setting-allowedTags

This is not, however, working for me with iframes, which is a whole other issue.


Search then loop through files that were uploaded via FTP

I figure out a solution thanks to Brad's suggestion to update the asset indexes. That allowed me to find all assets on the server that contained a partial match to my LogID number which I am passing in a URL string.


I would like to implement the remarketing tag into my website

I assume you're asking about AdWords?

Forgive me if I need to ask this but who developed your website? It sounds like you need to have your developer add that bit to the website's code. (If you're actually a developer and I'm talking under your knowledge, go ahead and modify your question!)

Otherwise, if have access to ftp or some other form of modifying files on your server, you can add it yourself. (Before you modify any file, make a duplicate copy in case you have to go back.)

The exact place is going to depend on your templates, located in the craft/templates/ and likely in the _layout.html (or some other file like header.html or footer.html).

If you're running Google Analytics (which is a safe bet, since you're using AdWords), the easiest way to do it would be to add a line to your GA tracking code which probably is already installed.  Just look for ga('send', 'pageview'); and add ga('require', 'displayfeatures'); right above that, as in the example given on the page (assuming you're using their newer Universal code).


How to make combination of two field values unique?

If I understood you correctly, you have two sections:

events
registrations

Is the user logged in? If yes, you can save the user id in your registration entry. In your events template you can check now, if a registration entry exists that is related to this event and the current user.
See example code (untested).

{% if currentUser %}

   {% set query = "userIdField:"~ currentUser.id %}
   {% set results = craft.entries({
      relatedTo: entry.id,
      section:'registrations'
      search: query
   }) %}

{% endif %}

{% if results|length %}
    user is already registered
{% else %}
    show registration form
{% endif%}

If your user is not logged in, you could (temporarily) store the registration information in a cookie (check out this plugin: https://github.com/lewisjenkins/craft-lj-cookies) and do a similar check.


Do I have to restart apache server every time I change a Craft PHP file?

No, but make sure devMode is turned on in your development environment.


Correct me if iam wrong but cant you just use the ElementCriteriaModel. Essentially because you are looking for an element type using that will give you much more flexibility - bassicly it is a query builder on roids.

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

    // Enter in params. here you can enter your sectionId
    $criteria->section = 'stories';
    $criteria->title   = 'Story One';
    $entries = $criteria->find();

This will return an array of all the entries that match this criteria. Ofcourse because this is craft you can thus enter a whole lot of other params and do some fancy stuff e.t.c..

I'll add two links at the bottom that are good reads on the subject:

https://craftcms.com/docs/plugins/working-with-elements

https://tighten.co/blog/craft-cms-building-complex-queries-by-extending-the-elementcriteriamodel


Prevent caching from inside of the cache tag

No you can't, but you might be able to cache each block individually rather than trying to exclude one of them.


Composer Error Updating Craft CMS 3 from RC13 to 14/15

Fixed this on several installations by changing the PHP and Yii versions to match what the system was running. It seemed to get out of sync now and then so had to keep on top of it at first on all of the Craft 3 installations. Once it's handled it doesn't pose a problem in the future.


It looks like using {{ dump(listItems) }} gave me enough to work with. I forgot to mention I had tried this before. It didn't work the last time, but I suspect I gave it an incompatible data type.


To Create a user do

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

To update a user

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

So it's basically the same except the scenario


Setting shipping costs on a per-product basis

Were I doing this, I would create a single (or an entry, or a global I guess) with a table (or maybe Matrix) field that would hold the shipping price chart.

I'd then create a custom shipping plugin in Commerce, that references this data and returns the shipping cost.

This would give a very nice UI for editing the products shipping, and would be a simple plugin to make.

Here's an example function that gets rate from a table:

public function getRatesForZone($zone, $slug){

    $criteria = craft()->elements->getCriteria(ElementType::Entry);
    $criteria->section = 'freightData';
    $criteria->slug = $slug;

    $ratesTable = $criteria->first();

    $rates = [];
    foreach ($ratesTable->postRates as $row){

        if($row['destinationZone']==$zone){
            $rates = $row;
        }

    }

    // If we reach here we couldn't find rates, return nothing
    return $rates;

}

Beyond that you just implement a shipping rule/method - see  https://craftcommerce.com/docs/shipping-methods

In this case, a small amount of custom code  will give both a better result and better UI I think, rather than trying to shoehorn in to the methods Commerce provides (although note I have not really investigated the Commerce methods much of late - I find custom shipping is usually the more controllable way to go!)


Search/Filter Freeform submissions by field value

This might not work, but you can try it like so:

{% set submissionCount = craft.freeform.submissions({
    form: 'myAmazingForm',
    fieldWithValue: '123',
}).count() %}


Short answer is "no, you can't have more than one parent."

Using relationships is probably the best answer. It's unfortunate that Luke didn't expand on his comments and add an official answer (in that other thread), but he was on the right track.

If you create a relationship field, you can relate your entry to as many other entries as you need.


Order products by lowest product variant

I managed to resolve this using the supersort plugin and using 'defaultPrice' instead of 'price'. Example below:

{% set products = craft.products.type('accommodation').all() %}
{% set order = products|supersort('sortAs', '{{ object.defaultPrice }}') %}

{% for product in order %}

    // Products

{% endfor %}


Show only products in stock - one variant only

You're always using variants. Just that if you have no 'other' variants commerce hides that stuff away. But your product has a defaultVariant behind the scenes.

Adding…

.hasVariant({ hasStock: true })

…to your query should (I think) return your products that have ([hidden] variants in) stock.


How can I bust a template cached plugin variable in a loop?

Left to itself, the {% cache %} tag will cache the content per-url. The problem you have is that the same url sometimes has $'s, and sometimes has GBP.

You can use the using key feature to cache based on the url and the currency:

{% cache globally using key craft.request.path ~ craft.geo.info.currency_symbol %}

(craft.geo.info.currency_symbol may not be the best disambiguator string, but this should get you started.)


You would have to hide the button or page where users could upload a photo.

To do this you could query for all that users entries with today's postDate. If the total is equal to or more than 10 then you'd redirect them to a different page or hide/disable the button that submits an entry.

Something along the lines of the following

add-image.twig

{% set todaysEntryCount = craft.entries.section( 'images' ) authorId( currentUser.id ).postDate( '> ' ~ now|date_modify('-1 day') ).total() %}
{% if daysEntryCount >= 10 %}
  {% redirect /your-images?message=dailylimit %}
{% endif %}

or

{% if daysEntryCount < 10 %}
   <button type="submit">Add your image</button>
{% endif %}


Does the Craft config var "cache" exist?

I don't believe this is a valid configuration value. You will use the cache as a tag in your twig files:

{% cache %}
    {% for element in entry.hugeField %}
        {{ element.nestedAsset.first().url }}
    {% endfor %}
{% endcache %}

The cache is most effective at nested queries in matrix fields or asset fields or category fields. Do not use the cache for plain text fields or those that can be accessed in linear time.

I would just delete that line from your config.php


Taken from this answer on Stack Overflow:
.htaccess mod_rewrite: rewriting querystring to path

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Remove index.php
    RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
    RewriteCond %{REQUEST_URI} !^/index\.php/admin\b [NC] # Don't mess with admin requests
    RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,NE,L]

    # Remove ?p=
    RewriteCond %{THE_REQUEST} ^GET\ /\?(([^&\s]*&)*)p=([^&\s]+)&?([^\s]*)
    RewriteRule ^(.*)$ /%3?%1%4 [L,R=301]

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

This not only reformats /?p=about as /about, but it also preserves other parts of the query string.

For example, /?p=about&tag=stuff and even /?tag=stuff&p=about both redirect to /about?tag=stuff.


How do I adjust the page title for different Section and Entry pages?

The title var can be set in the child templates, that way you can fine-tune it for each section of your site.

Take a look at these default templates:

news/index.html:

{% set title = "News" %}

news/_entry.html:

{% set title = entry.title %}

_layout.html:

The main layout just checks if it has been defined or not:

{% if title is defined %}{{ title }} - {% endif %}{{ siteName }}

.

P.S. Embed templates might be confusing at first, but are really great, check out the docs.


As Brad mentioned, you’re not getting any results because your search query requires both keywords to be present, but you don’t have any fields that have both keywords.

You can solve this with a hidden Preparse field that stores the content of all fields you want to be cross-searchable. Call it something like “Keywords”, and set its Twig template to:

{{ entry.myCustomFieldHandle }}
{{ entry.myOtherCustomFieldHandle }}

If you want to include any Matrix or relational fields in the keywords, remember the same templating rules apply here as on your front end templates:

{% for block in entry.myMatrixFieldHandle %}
    {{ block.myBlockFieldHandle }}
{% endfor %}

{% for relatedEntry in entry.myEntriesFieldHandel %}
    {{ relatedEntry.title }}
    {{ relatedEntry.myRelatedEntryFieldHandle }}
{% endfor %}

Once you’ve got that field set up and added to your section(s), you’ll need to re-save all of your existing entries before it takes effect. An easy way to do that is to go into the sections’ settings and just click the Save button, which will trigger a “Resaving Elements” background task for all entries in the section.


Regex to remove trailing slash not working

I think you are getting the twig replace filter (which does not have the regex capability) instead of the Craft replace filter (which does).

So this is a bug in Craft, in that their filter is masked by the twig one.

You could use the trim filter to remove trailing /s:

website|replace({'http://':''})|trim('/')

Or you could use one of Victor's Twig PCRE Filters.


Is it possible to tell Craft to ignore requests to under a certain path?

Have a look at the Routing article in the Craft Documentation, it describes why Craft handles these request in the first place:

  The .htaccess file that comes with Craft will redirect all would-be 404 requests over to index.php behind the scenes, which is why Craft is able to respond to URLs that don’t point to any actual folder/file in your web root.

A fresh Craft install's .htaccess file looks like so:

<IfModule mod_rewrite.c>
    RewriteEngine On

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

You'll notice that favicons are removed from the redirect. Add a similar RewriteCond for blog/ to also exclude request to your  WordPress folder from this condition.

    RewriteCond %{REQUEST_URI} !blog [NC]