Pagination with randomly ordered entries I have a need to list a set of entries 9 at a time but with a random order.

The pagination happens via Ajax, with each next set of 9 entries loaded onto the page when the user clicks the "See more" button.

I'm fetching the entries with

{% paginate craft.entries({
        section: 'customers',
        limit: 9,
        order: 'Rand()',
    })
    as pageInfo, pageEntries
%}

then looping through the set and outputting as normal

{% for customers in pageEntries %}

{{ customers.title }}

    etc.
{% endfor %}

and then adding a button to load the next set of results

{% if pageInfo.nextUrl %}
        See more
{% endif %}

I thought I had this figured out but I'm seeing some duplication in the returned entries. Oddly it doesn't feel like there is enough duplication to make me think my method is wrong. From about 100 entries, showing 9 at a time I might see 1 or 2 duplicates at most.

If I remove the order: 'Rand()' from my criteria then it all works fine (except obviously not in a randomised order).

Why am I seeing duplicates? If the randomisation was applied after 9 entries were retrieved then surely the first set of 9 would always be the same entries in random order. Likewise the second set, third set etc. Which isn't the case.

But if the randomisation is applied to the entire set of entries before the set of 9 is returned then why would there be duplications?

So I suppose the randomisation occurs on the full set every time and 9 entries are returned. But if this was the case surely I'd see more duplications.

Why is this happening?

  Why am I seeing duplicates?

When the database is told to sort by random, the entire list of entries is being sorted into a random order before your required page of items is being sliced out of it. This random sort is fresh and different every time the query is made, so when you ask for page 2, it's starting from a different random order, then slicing out items 10 through 18.

  Oddly it doesn't feel like there is enough duplication to make me think my method is wrong. From about 100 entries, showing 9 at a time I might see 1 or 2 duplicates at most.

I don't know how to calculate the exact probability, but I ran a little simulation, and assuming you mean you have 100 entries total and are looking for duplicates in two pages of nine entries each, you'd expect about 1 duplicate.

Solution

A solution is to pass in a seed value to RAND() so that it will use the same random order for each query. I've put '123' below, but I'm using the current day in my project so the order changes each day. You could also choose a randomized seed per user and remember it via a cookie or similar.

{% paginate craft.entries({
        section: 'customers',
        limit: 9,
        orderBy: 'RAND(123)',
    })
    as pageInfo, pageEntries
%}


How to install a Twig extension How do install a Twig extension in Craft? Not write my own extension, but install an extension that exists. I want to install the extensions extension. There are a number of posts that describe how to write your own extension, but I can't see how to just install one. The Twig docs says add this: $twig->addExtension(new Twig_Extensions_Extension_Array()); but obviously I don't want to edit core Craft.

I found this - How do you add a core twig extension in plugins using addTwigExtension()?, but the responses just convince the poster that he doesn't need to use that extension. What if he wanted to use it? How do you install it?

The BreakAndContinue plugin is an example of a plugin that adds a simple twig extension. I would start with that, and modify it to add the extensions extension (I assume that is this: https://github.com/twigphp/Twig-extensions ?) You might need to tweak the Twig PHP to get files to load etc., but not core Craft, since this will be a plugin.


Displaying disabled posts only to post author I have a simple photo gallery where logged in users can upload photos. I've set the default status for all pictures to disabled, is it possible to show disabled pictures only to user who just published it, and when status is set to enabled everyone can see it?

There are a couple of aspects to consider in your question.

Display entries to the author who created them
Display entries which are disabled

I'll assume your Channel/Structure is named "Gallery Image"...

First, establish the User ID of the logged in User:

{% set loggedInUserID = currentUser.id %}

...then find Entries authored by the Logged in User:

{% set galleryEntries = craft.entries.section('galleryImage').authorId(loggedInUserID) %}

(Entry Author ID parameter info...)

... then loop through any entries which have a Status of "Disabled"

{% for entry in galleryEntries.status('disabled') %}

Your draft Gallery entries

    ...(template code)...
{% endfor %}

(Entry Status parameter info...)

Another variation which you could use, which moves the Status parameter out of the For-Loop, is:

{% set galleryEntries = craft.entries.section('').authorID(loggedInUserID).status('disabled')%}
{% for entry in galleryEntries %}

Your draft Gallery entries

    ...(template code)...
{% endfor %}


Set User's entry field from PHP in Craft 3 From this question, I tried:

$user->setAttributes(['products' => $userProductsIds]);

return Craft::$app->getElements()->saveElement($user);

Where $user is an instance of craft\elements\User; and $userProductsIds an array. It's not giving me any errors, but the user is not updated. Any idea on what am I missing?

By checking vendor/craftcms/cms/src/controllers/UsersController.php and vendor/craftcms/cms/src/base/Element.php, I did it like

$user->setFieldValue('products', $userProductsIds);
return Craft::$app->getElements()->saveElement($user, false);


Output structure in a Given a structure that has, for example, three levels of content—how do I just iterate over it and create a nested
 reflecting the hierarchy and containing the title and slug (as a link) of each entry?

The following just gives me a flat representation of the structure:

People

        {% for entry in craft.entries.section('people') %}

{{ entry.title }}

        {% endfor %}

This could be achieved through a recursive macro:

{% macro recursive_nav(entries, depth) %}
{% import _self as self %}

    {% for e in entries %}

            {{ e.title }}
            {% if e.hasDescendants() %}
                {{ self.recursive_nav(e.children, depth+1) }}
            {% endif %}

    {% endfor %}

{% endmacro %}

And then to use it in your template:

{% import '_macros/recursive-nav.twig' as rn %}
{% set entry = craft.entries.section('people').level(1) %}

People

    {{ rn.recursive_nav(entry, 1) }}

This was borrowed and slightly modified from Marion's answer here. That question is also a great resource for other ways to achieve this result.


Allowed memory size of 1610612736 bytes exhausted when updating via CLI on OS X This one has been bugging me for months.

My development environment is running on MAMP on OS X. It's worked absolutely find for ages but for no reason that I can identify all my Craft sites now throw the following error when trying to apply updates via the craft cli:

./craft update craft

[snip]

Performing update with Composer ... PHP Fatal Error 'yii\base\ErrorException' with message 'Allowed memory size of 1610612736 bytes exhausted (tried to allocate 4096 bytes)'

Doesn't matter how much memory I give php, it will always eat it all up, exmaple of silly about of memory:

php -i | grep memory
memory_limit => 2048M => 2048

It will run for a good 2-3 minutes before throwing the error.

I assumed there was something odd with my local environment so held on as I was reloading the mac, but the issue has followed me to a fresh install.

I did notices the number of bytes it refers too is ~1.6GB, this figure doesn't change with php cli's memory limit, for example if I drop the limit to 512MB I get the same allowed memory size figure, which suggests to me there is another php binary in play here, but I don't know enough about how the craft cli works to troubleshoot that.

When this happens, in most cases I can complete the update using composer, but it's a hack that I don't want to continue with.

Versions are as follows:

Craft: All 3.1 and above, possibly 3.0 too but can't confirm
Mamp: 5.51
php cli: 7.2.21
Composer: 1.9.0
OS X: 10.14

Any ideas on how to troubleshoot this further?

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.


Push Notification plugin will not send iOS alerts when Craft CMS devMode is set to false The Push Notification plugin will send out alerts ONLY if devMode is set to true.

I can't leave my production environment in development mode so I'm trying to figure out why the alerts won't send when devMode is set to false.

I have checked the PushNotifications_PushService.php page and the logs will print out that Notified is 1 (which would be correct for my test). However, the alert never sends out. My phone never receives the alert.

My only assumption is that it deals with the APNSAdapter but that is coming from Sly/NotificationPusher. I've never worked with this class before so I'm not sure exactly how it works. Does anyone have any ideas what is going on?

UPDATE 1:

I am pretty sure the problem deals with the NotificationPusher class that the developer is importing. However, I'm not sure what is wrong with it.

See this: https://stackoverflow.com/questions/27611388/phonegap-pushplugin-with-notificationpusher-not-working-in-production

Here is an issue also posted on the NotificationPusher GitHub:
https://github.com/Ph3nol/NotificationPusher/issues/111

UPDATE 2:

Tested via command line using the following command:
./np push --certificate=/path/to/production_ck.pem apns deviceToken "Notification test"

This worked. No errors. Phone received alert.

Still not sure why it won't receive them from Plugin in Production Mode.

UPDATE 3:

I have placed log statements into the NotificationPusher class. I found no errors when comparing it to the "Dev" process.

I noticed when debugging the NotificationPusher project that it utilizes zendframework APNS to send the messages. My assumption is that the error must be somewhere within this project.

I found this: http://framework.zend.com/manual/1.12/en/zend.mobile.push.apns.html

In the first comment, he isn't getting any errors either but the alert is never getting to the device.

As far as the NotificationPusher project, I was able to determine that:

It is getting the device token and the message data
The response data is the same for both development mode and production mode. (However, the iPhone device never receives the alert message in production mode.) Still no error from code

Has anyone worked with the Zendframework? Any ideas what is going on?

UPDATE 4:

The only difference I have found so far is that the development mode uses the sandbox URL whereas the production mode uses the production mode.

What doesn't make sense is that I'm using my production certificate and it works on the sandbox URL but it doesn't work on the production URL.

I finally figured this out!

For any iOS application, in order to test the "Production" alerts to a physical iPhone Device -> You have to create an Ad-Hoc Application and deploy that to your iPhone device.

In order to do this, you must have an Ad-Hoc Distribution Profile created in the Member Center of "Certificates, Identifiers, and Profiles.

See this page for more information: https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/TestingYouriOSApp/TestingYouriOSApp.html

When using the Push Notification Plugin in debug mode, it works with the sandbox URL of Apple's Push Alerts. It will not use the production URL if you have debugMode set to true in the general.php file of Craft's configs.

Note: You will also have to set up the production certificate and configure that in the Push Notification Plugin settings to use the PEM file for the Production.

Once you deploy an Ad-Hoc Application to your iPhone device and have the PEM file setting pointed to your Production certificate, then everything should work fine (Make sure debugMode is set to false or remove this setting from the general.php file), the device will receive the alert.

I have tested this and it works on my iPhone 6 device.

Nothing is wrong with the ZendFramework or Push Notification code.

The issue was the deployment for the application on the iPhone device. I was testing directly from Xcode and using its build which is a development build (not an Ad-Hoc Build).


When using "Title Format", quotes in fields are entitized when saving to title field Example: section called people

Title format: {firstName} {lastName}

When I save an entry with the name _Michael "That Guy" D'Esopo, it saves and reads in the entries list screen as Michael &quot;That Guy&quot; D&#039;Esopo.

I've discovered a solution:
set the title format to {firstName|raw} {lastName|raw}

Should I just proceed that way?


Use .env values in Craft 3 plugin settings I’m writing a plugin and need some of its settings to be pulled from the .env file. According to the docs the following should work, but the getter isn’t getting called whenever the plugin’s youtubeApiKey setting is requested; it just keeps returning $YOUTUBE_API_KEY.
When I set the property visibility to protected instead of public, it does call the getter but also reveals the (sensitive) key in he admin settings panel.
class Settings extends Model
{
    public $youtubeApiKey = '$YOUTUBE_API_KEY';

    public function getYoutubeApiKey(): string
    {
        return Craft::parseEnv($this->youtubeApiKey);
    }

    public function behaviors()
    {
        return [
            'parser' => [
                'class' => EnvAttributeParserBehavior::class,
                'attributes' => ['youtubeApiKey'],
            ],
        ];
    }

    public function rules()
    {
        return [
            [['youtubeApiKey'], 'string'],
            [['youtubeApiKey'], 'default', 'value' => ''],
        ];
    }
}

I suppose my understanding of the settings getters is incorrect, but what I’m trying to achieve is for MyPlugin::getInstance()->getSettings()->youtubeApiKey to return the actual API key (not $YOUTUBE_API_KEY) and for the settings field (below) to display $YOUTUBE_API_KEY (not the actual API key).
{{ forms.textField({
    'id': 'youtubeApiKey',
    'label': 'YouTube API key',
    'name': 'youtubeApiKey',
    'suggestEnvVars': true,
    'value': settings.youtubeApiKey
}) }}

You could try declaring the variable $youtubeApiKey with no value set. Instead of using
public $youtubeApiKey = '$YOUTUBE_API_KEY';

try using
public $youtubeApiKey;


Why does Bootup.php run with PHP 5.4.16 from with Craft script but PHP 7.4.10 from the terminal command line? This is a problem encountered apparently by a lot of users when installing from the Craft setup/install files from the Craft web site.
PHP Warning: Unsupported declare 'strict_types' in /var/craft/vendor/voku/portable-utf8/src/voku/helper/Bootup.php on li PHP Fatal error: Default value for parameters with a class type hint can only be NULL in /var/craft/vendor/voku/portablec/voku/helper/Bootup.php on line 27 Script @php craft setup/welcome handling the post-create-project-cmd event returned with error code 255
The following scenario yields this error:

A fresh install of craftcms

installed with composer

using these instructions: https://craftcms.com/docs/getting-started-tutorial/install/files.html#what-s-composer

On a bran new unused DigitalOcean Plesk/Centos7 machine

with php aliased to the Plesk php 7.4 folder

With CLI php -v verified as returning 7.4

With all the required php extensions

With the web server visited and phpver command verified as returning 7.4

with composer updated
# composer depends danielstjules/stringy
# voku/stringy 6.4.0 replaces danielstjules/stringy (~3.0)

Diagnosing it, Right, putting echo phpversion(); into Bootup.php and running from Bash returns 7.4.
But comment everything in Bootup.php out, put echo phpversion(); into it and run craft, and when it calls Bootup.php, it returns 5.4.16.
Why is this?  Why does it run with a different php version when run from within the Craft script, and how is this fixed to run with 7.4?

Where did you define your aliases? If you haven't already, you could start by adding directives for both php and composer in your .bash_profile.
The file should contain something like (alter paths as appropriate):
# Include the location of the PHP 7.4 binary in your path
export PATH=/opt/plesk/php/7.4/bin:$PATH
# Ensure that any calls to composer are run with the PHP 7.4 binary
alias composer='/opt/plesk/php/7.4/bin/php /usr/lib64/plesk-9.0/composer.phar'

Log out/in (or source .bash_profile) and run php -v to check it's picking up the correct binary, then have another go.


How can I efficiently show the number of total results per channel when retrieving search results? I have a site with a few channels each with a lot of entries. When retrieving the results from a site search, I’d like to show a paginated list of entries from all sections by default, but then have filters in a sidebar which retrieve only entries from a certain channel, again in a paginated list.

How can I initially show the total number of entries in each channel for a particular search term, without having to actually construct a query for each channel individually which would be really slow?

The behaviour would be identical to the following example where it lists the number of entries for each ‘Material type’ http://explore.bl.uk/primo_library/libweb/action/search.do?dscnt=1&tab=website_tab&dstmp=1461161587439&vl(freeText0)=family&fn=search&vid=BLVU1&mode=Basic&fromLogin=true

I would try one of the following solutions:

Using Ajax to display the search results and the filter
Use ajax to display your search results. After loading the search results, you'r using a second Ajax call to get the categories filter. With this solution the visitor see the results quickly and get the filter after. You could try to including caching of the filter to speed up the page. Downside: Depending on requests and amount of content, it needs still a lot of server power.

Writing your own Plugin
Write your own search filter plugin with your logic and optimized SQL to get the filter faster. This solution can be combined with the first one.

Using a external Search Engine
A other solution could be to use a external search engine service like Google Custom Search. Some of them offers filters/logic like you need. Craft CMS Example: On https://straightupcraft.com/craft-plugins/ the search is provided by Algolia (https://www.algolia.com/). On the right side is a simple developer filter, including number of entries.
Take also a look at the Algolia Plugin to easy integrate Algolia in Craft CMS -> https://straightupcraft.com/craft-plugins/search-plus-1


Restrict entry editing to category / topic How can I implement security which allows members to only publish an entry in an assigned category / topic?

Example:

The site is a business directory.
Business listings are published in cities: New York, California.
Content managers are assigned to either New York or California.
Content managers can only publish in the city they are assigned to.
Content managers can only see entries in the city they are assigned to.

I first thought this could be done with a custom field that only shows the cities a content manager is assigned to. That shouldn't be so hard.

However I'd need to also limit the entry indexes in the Control Panel.

Edit: Just found the onBeforeBuildElementsQuery event: https://craftcms.com/docs/plugins/events-reference#elements-onBeforeBuildElementsQuery

    craft()->on('elements.onBeforeBuildElementsQuery', function(Event $event) {
       // $event->params['criteria']['tennant'] = 'new-york';
    });

Any ideas?

So you could definitely use the onBeforeBuildElementQuery event to keep them from showing up in the CP (though you'd have to detect if the query is coming from the CP).

I'd also recommend your plugin uses the onBeforeSaveElement event. From there you could check the element's related categories to see if the user has them on their user account, and then allow/deny them to be able to save the element from there. While hiding it from the CP would likely keep them from finding it, putting in more validation will make sure that no one emails an edit link to someone who isn't supposed to be able to edit it.


Updating global set from controller This is my code:

$giveaway = Craft::$app->globals->getSetByHandle('promotions');
$giveaway->giveawayName = "New Name";
$success = Craft::$app->globals->saveSet($giveaway);
return($success);

Controller returns true, but no changes have been made to the "promotions" global set. What have I missed?

Oli’s comment is mostly right, but I think the solution is event simpler—the method you discovered is specifically for saving the GlobalSet settings/definition (like its name, handle, and the fields it uses), but what you're looking for is a more generic method for saving the Element that contains the actual content (as though you were updating it from the main Globals menu in the CP):

// Generic save method for any Element type, including Globals:
Craft::$app->getElements()->saveElement($giveaways);

✌


Commerce 3 upgrade question We're about to launch a Craft Commerce 2 site. I'm wondering how involved the Commerce 3 upgrade is as far as template changes? And if we decide to upgrade now what's the best practice for making those changes? Start with the new templates and add our customizations?

Will the Stripe for Craft Commerce work with Commerce 3? I notice it just lists Commerce 2 right now.

Commerce 3 is not a major change from Commerce 2 - you can see what you need to do to update here:

https://docs.craftcms.com/commerce/v3/upgrading.html

Stripe works with Commerce 3 without any update needed: https://github.com/craftcms/commerce-stripe/blob/develop/composer.json#L28


Extending a block from another page My orignal website is a Onepager but I am creating a individual news page.

Is it possible to extend a block to another page taking over the content from that single? I have a block filled with a really big Matrix field which I cant have on my other page cause I only need a small amount of content from it. This content is placed inside a block so I need to extend just that block.

What I need is to extend the {% block navigation %} and not the entire page

See it as this:

{% block navigation %}
  {% for block in entry.blokken %}
    {% if block['opnemenInNavigatie'] is defined and block.opnemenInNavigatie %}

        {% if block.navigatieNaam | slugify == 'news' %}

          {{ block.navigatieNaam }}

       {% endif %}

    {% endif %}
  {% endfor %}
{% endblock %}

And also this:

{% block content %}
    {% for block in entry.blokken %}
        {% include 'blocks/' ~ block.type ~ '.html' %}
    {% endfor %}
{% endblock %}

I'd just put whatever you want to share into an include. Also you shouldn't need the .html either as craft should find the file


S3 Asset uploading hangs I am having an issue with uploading assets to S3 from Craft.  So far I have taken the following steps:

Create permission policy and attached to group containing craft
user:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListAllMyBuckets"
            ],
            "Resource": "arn:aws:s3:::"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetBucketLocation",
                "s3:ListBucket",
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject",
                "s3:GetObjectAcl",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::<bucket_name>/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetBucketLocation",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::<bucket_name>"
            ]
        }
    ] }

Create new asset source with type of Amazon S3 and input access and
secret key for craft user.  This allows me to select the available
bucket.
Save the asset source and go to the asset section to upload a file
to S3.  At this point the status bar fills up and the upload hangs
indefinitely.

Other notes:

These are very small images (<100KB)
I am able to bring images into Craft if I upload them directly to S3
and then update asset indexes in the setting.
I also noticed that the error logs print out the message:

  exception 'S3Exception' with message
  'S3::getObjectInfo([bucket_name], [file_name]): [52] Empty
  reply from server' in
  /Users/[user]/Sites/[project]/craft/app/lib/S3.php:777

I have also tried using the more broad 'AmazonS3FullAccess' policy
with the same results.

EDIT:
In continuing to explorer this issue I have found that a call is being made from the S3AssetSourceType file in the insertFileInFolder function to the S3 class getObjectInfo function.  It seems like this error is occurring because the code is trying to fetch information from amazon on an object that does not yet exist because this call occurs prior to the put object call.  I have yet to understand why the getObjectInfo is called within the insertFileInFolder call before a put object request is made to S3.

EDIT 2:
After more troubleshooting and testing this on a remote server it looks like the issue has to do with our company firewall not allowing receipt of the response object from the S3 request.  We had no issues uploading assets to S3 from the same codebase on a remote server and are now looking into a work-around with the firewall.

Per the original poster's 2nd edit, the issue had to do with their company firewall blocking the request to S3.

  After more troubleshooting and testing this on a remote server it looks like the issue has to do with our company firewall not allowing receipt of the response object from the S3 request. We had no issues uploading assets to S3 from the same codebase on a remote server and are now looking into a work-around with the firewall.


Plugins not showing in Admin I'm experiencing a problem where none of the plugins (2 captchas, and a random bookworm plugin) are showing up in my admin panel.

Folders are lowercase.

I've also checked permissions; folders are at 755. The corresponding file is at 644.

I have the Pixel & Tonic Contact Form plus the RetconHTML plugins currently in there, so I know I've successfully uploaded plugins before. Just not sure what's going on.

Thoughts?

-edit-

The two plugins I'm currently having problems with are bookworm and recaptcha, not anything I've specifically developed.

Here's a screenshot of my plugins directory:

Probably the name of the folder isn't the plugin handle. Check inside the plugin's folder to see if the actual plugin folder is inside there. For instance:

forge@nys-production ~/nystudio107.com/craft/plugins (master) $ tree -L 1 craft-typogrify/
craft-typogrify/
├── readme.md
└── typogrify

In this case, when the plugin is downloaded or cloned, the name of the folder is craft-typogrify but the actual plugin folder is inside of this folder, and is named as a lowercase version of the plugin handle: typogrify.

This is what needs to be directly in the craft/plugins folder for Craft to see it.


Craft 3 Custom Plugin: model validation Struggling a bit here - have created a custom plugin where I want to validate form submission against a predefined model before saving to the database. All pretty straightforward so far …

However, if I try to use native (Yii 2) validation then a record is saved regardless of whether it is valid or not. For example, if I set the model rules as follows:

public function rules()
    {
        return [
            [['formName'], 'required'],
            [['formName'], 'string', 'min' => 1, 'max' => 255, 'skipOnEmpty' => false]
        ];
    }

The record is saved, even if $model->formName is empty. For example, see the following Controller code:

public function actionUpdate()
    {
        $this->requirePostRequest();
        $request = Craft::$app->getRequest();
        $site = Craft::$app->getSites()->getCurrentSite();

        $formName = $request->getBodyParam('formName');
        $formId = $request->getBodyParam('formId');

        // get ID (if exists)

        if ($formId) {
            $formRecord = FormRecord::find()
            ->where(['id'=>$formId])->one();
            // if count == null return false
        } else {
            $formRecord = new FormRecord;
        }

        $formRecord->formName = $formName;
        $formRecord->siteId = $site->id;
        if ($formRecord->validate()) {
        …

The code will always validate - even if the formName is empty.
This seems a bit crazy to me - am I misunderstanding something about Yii validation rules here?

Help/thoughts appreciated,

Cole

I am a beginner at craft cms,but  I think these would help you:-
1.install the plugin guest entries and look at their code
2.look at this article


Why does asset uploading fail with the error "Uploaded file was empty"? Recently I've noticed that file uploads through the Craft admin panel have started to fail with the response "Error uploading the file: Uploaded file was empty". This error occurs when trying to upload a file to the server or to S3.

At first, I was able to get around the issue by switching to a different browser or clearing the current browsers history and cookies. For some reason that would consistently alleviate the issue for any user who tried it, but as of last week this no longer appears to work.

So far I have tried:

Checking file permissions for the asset folder, they're set to 777
Increasing the php memory_limit, post_max_size, and upload_max_filesize
Uploading different file types and sizes looking for specific type or size that works, even a 20kb jpg fails.

Has anyone seen this before or have an idea where to look to fix the issue?

You'll get that message whenever Craft/PHP can't upload the file (for any number of reasons).

Looks like you've covered permissions and some common php.ini environmental limitations.

If it's happening of every file regardless of file type or size, you can probably rule out any GD or Imagick related bug.

Other things to check for:

You're out of disk space on your hosting account.
You're out of allocated space for the /tmp folder on your account.
There is some firewall / .htaccess rewrite rule / Suhosin / mod_security blocking the request.

It's probably worth checking craft/storage/runtime/logs for any errors as well as your web server's error logs.


Updating old setup (3.0.41.1) to 3.1.0 various errors every time I'm unfortunately dealing with a very old system that hasn't been updated in a long time. I've been able to update it up to 3.0.41.1 but once I attempt to go any further I get tons of different errors. They primarily seem to be migrations. I keep having to do a restore of the DB I'm working with over and over to try to sort this out but I'm not sure what else to be looking for.

Any recommendations? (besides updating things at the right time?)

UPDATE 1:

When attempting to update from the web interface (which i think attempts to go straight to 3.4.5) I consistently get the following error:

Composer output: Package "craftcms/vue-asset" listed for update is not installed. Ignoring.
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

Problem 1
- Installation request for craftcms/cms 3.4.5 -> satisfiable by craftcms/cms[3.4.5].
- craftcms/cms 3.4.5 requires twig/twig ~2.12.0 -> satisfiable by twig/twig[v2.12.3, v2.12.2, v2.12.1, v2.12.0] but these conflict with your requirements or minimum-stability.
Problem 2
- spicyweb/craft-embedded-assets 2.0.12 requires craftcms/cms ^3.0.0 -> satisfiable by craftcms/cms[3.4.5].
- spicyweb/craft-embedded-assets 2.0.12 requires craftcms/cms ^3.0.0 -> satisfiable by craftcms/cms[3.4.5].
- spicyweb/craft-embedded-assets 2.0.12 requires craftcms/cms ^3.0.0 -> satisfiable by craftcms/cms[3.4.5].
- craftcms/cms 3.4.5 requires twig/twig ~2.12.0 -> satisfiable by twig/twig[v2.12.3, v2.12.2, v2.12.1, v2.12.0] but these conflict with your requirements or minimum-stability.
- Installation request for spicyweb/craft-embedded-assets 2.0.12 -> satisfiable by spicyweb/craft-embedded-assets[2.0.12].

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

There used to be a bug in Craft 3.0 (fixed in 3.0.19) where, if an error occurred during an update, your composer.json file could be left in a weird state where it was directly requiring all of Craft’s dependencies (recursively). My guess is that this happened to you.

Try opening your composer.json file and see if your require setting contains a whole bunch of dependencies, such as twig/twig.

If so, then just delete all of the dependencies that don’t need to be in there. If the file is tracked in Git, then you should be able to look up its history and find the point where all of the extra dependencies were added. Otherwise you’ll need to figure that out for yourself.

You definitely need craftcms/cms.
You probably need vlucas/phpdotenv, if any of your environments are using a .env file.
If you have any plugins installed, then each of them will have one corresponding dependency.
Beyond that, everything else should be safe to remove (unless you intentionally added something else).

Once you’ve removed everything you don’t need, try changing your craftcms/cms requirement to ^3.4.5 and then run composer update. As a sanity check, pay attention to which dependencies get removed in the process, in case you accidentally over-corrected.


logo uploaded through backend doesn't come through (on my environment) I've got a logo uploaded through the backend, I've got the file locally & can see it on the craft login screen and the backend.

Colleague can see it fine on the front end on a template, but I cannot.

Loading it in on the front end with: {{ craft.rebrand.logo.url }}

It just seems to timeout while the page is being loaded:

Storage folder is 777'd recursively, I presume it's loading it through that (due to the /cpresources/ path)

Anyone got any ideas?

My colleague had used a  local server name 1 char different to mine.

The domain I was using didn't match the "siteUrl" param in the general config.

The image was loading in with a different domain to what I was on.


What's the purpose of multiple asset sources? If I have just one S3 bucket, should I still have multiple asset 'sources' in order to account for different asset types? Or should I just have multiple folders under single asset source to differentiate media types?

For example, I might have these folders under a single asset source:

Illustrations/Icons
Marketing Images
Screenshots
Marketing Videos
Support Videos

It just seems silly to add multiple asset 'sources' when the details are the same.

You should use the bucket directory structure for the different asset types; you're right, they are all coming from the same source, really, so separete asset sources wouldn't be correct.

Another asset source would be simply another bucket, or another type of source such as Google Cloud or Rackspace.

You could have an asset source called Web S3 Assets, which connects to your bucket.

As an example, you could have these directories within that bucket for all the types of assets you need to store.

<bucket-url>/images/icons/
<bucket-url>/images/illustrations/
<bucket-url>/images/screenshots/
<bucket-url>/videos/marketing/
<bucket-url>/videos/support/

Use Assets Fields to force usage, upload restrictions on these directories.


A hash key must be followed by a colon (:) syntax error Trying to get entries between two dates and am getting: 'A hash key must be followed by a colon (:). Unexpected token "operator" of value "~" ("punctuation" expected with value ":")'

{% set posts = craft.entries({
    section: animal,
    orderBy: "postDate" })  %}

{% set puppyAnimals = posts({
    animalDateOfBirth: 'and',  ">= " ~ now|date , '<=' ~ now|date_modify('-1 year')|date })  %}

It's Craft 3 so I may just have the syntax wrong.

You're nearly there! The and query you’re building just needs to be declared as an array:

{% set puppyAnimals = craft.entries({
    section: 'animals',
    orderBy: 'postDate',
    animalDateOfBirth: ['and',  "<= #{now | atom}", ">= #{now | date_modify('-1 year') | atom}"]
}).all()  %}

The brackets around the value provided for animalDateOfBirth was being interpreted as a single string, followed by a missing key.

(I also opted for Twig’s interpolation syntax to make the series of array elements a little clearer, and used the atom filter to produce fully-qualified dates)

  One more note: I switched the greater-than and less-than operators, as I suspect the query would have returned no results—(after today, but earlier than last year)!


Show user group in CP user listing? I want to scan my user list to see if anyone hasn't been assigned to a group.

Is there a way to show user groups as a column at admin/users?

There isn't a way baked in to Craft - probably something to do with the fact that users can be in multiple groups. Although I totally agree it would be useful, like at least listing the first group they're in, like the Entries view does with Categories.


How do you use a Matrix to toggle between multiple fields from multiple blocks? I have 1 Matrix field:
contentBlock

With 2 Block types:
text
photo

With nested fields:
text -> text
photo -> photo

My attempt at using if statements, which didn't work, to toggle between text and photo looks like the following:

{% for block in entry.contentBlock %}
    {% if block.type == 'text' %}
        {{ block.text }}
    {% endif %}
    {% elseif block.type == 'image' %}
        {% set image = block.image.first() %}
            {% if image %}
                <img src="{{ image.getUrl('thumb') }}" alt="{{ image.title }}">
            {% endif %}
{% endfor %}

Would using {% switch %} be a better method, or was I close to correct using the if statements?
I think getting the hang of this will open up the true posibilities of using Craft Matrix fields.

Thank you for any input on this question.

Using switch is a good way to handle this, but it looks like your conditionals are just a little off:

{% for block in entry.contentBlock %}
    {% if block.type == 'text' %}
        {{ block.text }}
    {% elseif block.type == 'photo' %}
        {% set photo = block.photo.first() %}
        {% if photo %}

        {% endif %}
    {% endif %}
{% endfor %}

The same thing with the switch syntax would be:

{% for block in entry.contentBlock %}

    {% switch block.type %}
        {% case "text" %}
            {{ block.text }}
        {% case "photo" %}
            {% set photo = block.photo.first() %}
            {% if photo %}

            {% endif %}
    {% endswitch %}

{% endfor %}


Is it possible to use an existing field into a matrix? I'm trying to reuse a dropdown field inside of a matrix. I've already created a field which has hundreds of dropdown values. I want to be able to select from this dropdown field for each item of a matrix. So instead of having to re create this field for each matrix block, is there a way I can copy/paste a field to a matrix field?

Thanks in advance!

You can use the neo Plugin or you can copy and paste the field settings manually from one field to your matrix field in your database interface. In your craft_fields table there is a column settings you can search for your field handle and copy the settings to your new field.

You'll not be able to do this without a custom plugin or copy pasting the values via SQL in any way


Customising the new CKEditor5 in Craft 3 How do you configure the new CKEditor editor to e.g. add images? Do you create a config/CKeditor folder with a .json file and install the @ckeditor/ckeditor5-image package?

I don't think so. You can see the entire code here

ClassicEditor
    .create(document.getElementById('{$nsId}'))
    .then(function(editor) {
        $(editor.element).closest('form').on('submit', function() {
        editor.updateEditorElement();
    });
})

This is the javascript that triggers the editor, as you can see, there are no config settings provided yet. I searched in the entire plugin but I could not find any other Javascript functions that are triggert so unless they provided a really nasty method to include them in the original editor js file you can't change them yet.

The only "configurations" are Html Purifier

Edit

However - you could create a feature request or you could implement your own code to provide settings. You only need to change a few lines - it's totally trivial


Use Craft.postActionRequest in frontend template Until now I've always done backend plugin development but my next task is to create a homepage with craft. To make an Ajax request I used Craft.postActionRequest but if I try this in my frontend template I always receive the error Uncaught ReferenceError: Craft is not defined

I've tried to include {%- includejsresource "js/craft.js" first -%} but it does not work. Of course I could just create a normal request via Ajax/jQuery but I would like to do it with craft methods...

So my question: what do I have to do, to get access to craft.js library?
edit: Just like this https://craftcms.com/docs/plugins/controllers#posting-to-controller-actions-with-javaScript

Thank you very much

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

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

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

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


how to set loginPath in config file I made a modal for login at homepage and put {%requireLogin%} tag in "User Profile" page.
My general.php file looks like below:

'dev' => [
        // Base site URL
        'siteUrl' => null,

        // Dev Mode (see https://craftcms.com/support/dev-mode)
        'devMode' => true,
        'loginPath' => '/',
    ],

I hope to prevent users to go to "User Profile" page without login and redirect them to homepage. But the issue is when I login on the homepage, the browser gives an error redirected you too many times.

Any idea how to do that please? Many thanks!!

OK, no one answered....I have to take another way to do which is to put a piece of code like this into user-profile page

{% if not currentUser %}
  {% redirect '/' %}
{% endif %}

and take out loginPath setting in config file.


Additional code to run when cache is busted(entry added/updated, etc) I'm using Craft Pro 3.6 in Headless mode.  I've found that caching the GraphQL responses on the frontend server dramatically speeds up our load time, even with enableGraphQlCaching turned on.
What I'd like to do is have Craft make a cUrl request to an endpoint on our frontend server whenever an entry is published or updated(or whenever the cache busting script would normally run) to clear the frontend cache.
I'm guessing the best approach would be a custom plugin?  However, if there's an easier way to do this I'm all ears.
Thanks for your time.

Sounds like a custom plugin or module would work for you here, allowing you to hook into the entry after save event.
use craft\elements\Entry;
use craft\events\ModelEvent;
use yii\base\Event;

Event::on(
    Entry::class,
    Entry::EVENT_AFTER_SAVE,
    function(ModelEvent $event) {
        $entry = $event->sender;

        if (!$entry->getIsDraft()) {
            // Make the request to clear caches on the frontend.
        }

    }
);


Send e-mail notificacion ( including attached files ) after user send information with Guest Entries I´m using Guest Entries to add to db some info filled by users, including some attach files. Everything works great.

But now i have to send an email with all the info and files that user send, i´m already using Postmaster plugin to send a notificacion, it works, but it doesn´t send the attached files ( i mean, i don´t know how to do it ).

Is there a way to do this with the plugin or another way?

Thanks for your help.

Instead of using the Postmaster plugin, which appears abandoned and hasn't been updated since 2016, you could write a simple plugin that listened to the afterSaveEntry event.

That plugin could grab any info from the submitted Entry model, including uploads/attachments, and manually compose and send an email out.

You can see an example of how to do that in code in the Contact Form plugin.


Tagging all assets in a sub directory I'm building a project with a lot of photo assets organized into sub directories of the main photos asset source. I'm trying to add tags to these assets so they are searchable when I try to use them in my entries.

With native features of Craft, this process seems to be very manual, I just have to click on each of these asset files and add the tags that I want.

Is there a way, either using a plugin or make a MySQL query, to bulk add tags to all the asset files under a certain sub directory?

Seems doable with a custom plugin.

The pseudo-code would be something like:

Use AssetsService to grab all of the files for the source.
Loop through the files and parse the parent folder paths.
Based on the subfolder for the asset, check if an existing tag already exists with the TagsService.
If 3 is true, assign that tag's value to a tag field on the Asset.
If 3 is false, create the tag using the TagsService, then assign that tag's value to a tag field on the Asset.


Mandrill integration not sending email for front-end registration form Update Emails only send out when you're not logged in as admin from the registration form.

No errors received in dev mode, user created, but no activation email sent. Definitely not getting passed to Mandrill as Little Snitch checks outgoing connections.

The weird thing is, user activation from the admin does send an activation email.
Verify email addresses? in system > users is selected.

It should send an activation email out, right? Or are you supposed to activate every new user via admin?

Emails only send out when you're not logged in as admin from the front-end registration form.


Plain text field - apostrophes are getting escaped I have a plain text field in Craft and the content has an apostrophe. On the front end, the apostrophe gets turned into &#039;

Not ideal! Thanks in advance..

The only way I can see this happening is if the field was originally a Rich Text Field, the content was entered, then the field type was swapped to a plain text field.

If that's the case, the Rich Text Field would have encoded the entities and saved them into the database.


Variable "entrySlug" does not exist Routing I currently have a routing set up as follows to enable an "Edit" entry page following on from this question but I'm getting the following error message when going to that page.

  Variable "entrySlug" does not exist

I have my routing set up as follows within my CP, which loads a URL like so mydomain.com/marketplace/authorname/entryname/edit

and within my listings/_edit

{# Find the entry by slug and author: #}
{% set listing = craft.entries({
    section: 'networks',
    slug: entrySlug,
    author: currentUser
}).one() %}

I'm really unsure why it can't find the slug of the entry.

If I'm not mistaken, I don't think setting up the route via the CP does the fancy advanced rule stuff described here. You'll therefore want to do that via the config/routes.php file with something like this:

'marketplace/<authorSlug:[^\/]+>/<entrySlug:{slug}>/edit' => ['template' => 'listings/_edit'],

Now authorSlug and entrySlug will be available for use in your listings/_edit.twig template...


Return all cache records, delete caches with prefixed keys Does craft()->cache-> have a way of returning all the cache records?
I need to delete some caches, but only if the key begins with a certain prefix, “ranking__getAthletePoints_”. I won’t know the numbers following in the key names. If I could grab all of them, I assume I could check against the key names with something like startsWith() and delete the correct caches that way.

Very much out of my element with php & plugin development! Thanks for any help!

Not without some brute-force cracking.

The keys you pass into CFileCache's set and get methods are an md5 hash of your key prepended with your Craft installation's appId (which by default is a randomly generated string).

So with a key of testKey, that could end up as a value of 3f8b3c45a9c6f395d02b930f18910a92.  For CFileCache, that value ends up being the file name of the cache file and gets put in craft/storage/runtime/cache/3f8b3c45a9c6f395d02b930f18910a92.bin.

Later, when you call get and pass in the key of testKey, it goes through the same process and checks to see if a file named 3f8b3c45a9c6f395d02b930f18910a92.bin exists.  If it does, it knows there is a match.

As you can see, there's no way to find that match without knowing the key ahead of time (unless you brute-force cracked md5, which is doable, but probably not practical for your use-case).


Organize filtered entries by a specific category I have an array of products that has already been filtered by a brand category. I want to display them in a list ordered by a size category. This is working, but I think there must be a better way:

{% set productList = craft.entries(params) %}
  {# where params includes a relatedTo parameter already #}

    {% for size in sizes %}
        {% for product in productList %}
            {% if product.sizeCategory.first.id == size.id %}
                {{ product.title }}<br />
            {% endif %}
        {% endfor %}
    {% endfor %}

You should be able to order them using a combination of the order method (if needed) and group twig filter.

{% set productList = craft.entries.(params).order('title')|group('myCategoriesField.first().title') %}

The problem here is that the products might end up being displayed in the order that the size categories were created (i.e. postDate) and not the category 'size' title. If this is a problem then your solution may in fact be the only way. Have a look at this question for alternative answer and discussion of some of the issues.


Way for clients to edit translation file(s) in control panel? We have some navigation links being translated via the /translations folder but the client needs the ability to change them too...

Is there a way to make the translations editable from the control panel?

I would say the most cleanest way is to handle all translations via Yii2 DbMessageSource.

You could say you want to store all translations into the database instead of files.
There is an MessageSource::EVENT_MISSING_TRANSLATION event in which you can store all translations into your new database table. As soon as Craft recognizes a new translation you'll have the chance to insert the new record

Here is a code snipped from our translation plugin

Event::on(
    MessageSource::class,
    MessageSource::EVENT_MISSING_TRANSLATION,
    function(MissingTranslationEvent $event) {
        if ($event->message) {
            $message = Translate::getInstance()->getTranslation()->addMissingTranslation($event->category, $event->message, $event->language);
            if ($message instanceof Message) {
                $event->translatedMessage = $message->translation;
            }
        }
    }
);

Your DbMessageSource class could look like this

class DbMessageSource extends \yii\i18n\DbMessageSource
{
    public $fallback = [];
    public $useMultiSiteTranslationFeature = false;
    protected $fallbackClass;

    /**
     * Return something for everything which is requested
     *
     * @param string $name
     *
     * @return mixed|null
     */
    public function __get($name)
    {
        try {
            return parent::__get($name);
        } catch (\Exception $e) {
            return null;
        }
    }

    /**
     * @param string $name
     * @param mixed  $value
     */
    public function __set($name, $value)
    {
        try {
            parent::__set($name, $value);
        } catch (\Exception $e) {
            $this->$name = $value;
        }
    }

    public function translateFallback($category, $message, $language)
    {
        if ($this->useMultiSiteTranslationFeature && Craft::$app->getRequest()->getIsSiteRequest()) {
            $this->useMultiSiteTranslationFeature = false;
            $translated = $this->translate($category, $message, $language);
            $this->useMultiSiteTranslationFeature = true;
            if ($translated) {
                return $translated;
            }
        }
        if (count($this->fallback) === 0) {
            return false;
        }
        if (!$this->fallbackClass) {
            $this->fallbackClass = \Yii::createObject($this->fallback);
        }

        return $this->fallbackClass->translate($category, $message, $language);
    }

    protected function loadMessages($category, $language)
    {
        if ($this->useMultiSiteTranslationFeature && Craft::$app->getRequest()->getIsSiteRequest()) {
            $category .= '_' . Craft::$app->getSites()->currentSite->handle;
        }

        if ($this->enableCaching) {
            $key = [
                __CLASS__,
                $category,
                $language,
            ];
            $messages = $this->cache->get($key);
            if ($messages === false) {
                $messages = $this->loadMessagesFromDb($category, $language);
                $this->cache->set($key, $messages, $this->cachingDuration);
            }

            return $messages;
        }

        return $this->loadMessagesFromDb($category, $language);
    }
}

The rest is common Craft work to create create a custom form/list for your new CP section or you create an element type and let Craft handle everything.

As you can see in the picture below: all translatable strings from all sources/categories/plugins are recognized and our customers are able to change all translations in all plugins into all languages. Even if the creator of the plugin never wanted to include certain translations into certain languages


How to disable element editor on custom element type? I'm working on custom element type and I'd like to disable the editor modal at element index view that appears when you double-click on status icons/thumbnails in the title column. Any help?

The Element Editor HUD will only be available if your element model’s isEditable() method returns true. (It returns false by default.) Remove that method from your element model class and you should be good.


PHP warning with composer on MacOS High Sierra: Failed to open stream We have multiple people working on a craft site using Vagrant and Virtual Box for our local server.

I am running MacOS Sierra, and everything works as expected. A couple of our other developers have updated to run High Sierra, and when they would pull down the git repo for the project this error shows up:

  include(/vagrant/app/craft/app/vendor/composer/../twig/twig/lib/Twig/Source.php): failed to open stream: No such file or directory

This happens when Vagrant is up and running successfully, gulp is watching, and all the user is trying to do is connect to localhost:3000 through their browser. These computers had successfully worked on the project in the past before updating their OS.

We tried doing a fresh pull down of the repo on a computer that had never worked on the project (but also using High Sierra) and we get the same exact error. So the only thing we know that is different between my computer (which works as expected) and the others is that mine is running Sierra and the others are running High Sierra.

We've tried searching online for this issue, but haven't found anybody posting similar enough problems. Also, I am posting this here since it is a Craft CMS project, so if I should switch this to a different stack exchange, let me know. Thank you!

SETUP INFO:

config.vm.box = "ubuntu/trusty32"
config.vm.box_url = "https://vagrantcloud.com/ubuntu/boxes/trusty32"

Tools:
Vagrant, Virtual Box, Gulp, rsync installed through homebrew

Let me know if there is anything specific about our setup that you'll need to see to be more helpful.

It sounds like you're running into this recent Composer autoloading bug: https://github.com/composer/composer/issues/6977

Chances are if you composer self-update, the issue will go away.


BE formatted dates not imported correctly (or not at all) I've also raised this question / issue at https://github.com/engram-design/FeedMe/issues/255 but this forum might be a better a place as I'm unsure if it is a bug actually

FeedMe uses date_parse to parse dates in an inbound feed. This usually works out great, the problem I have now is a certain XML-feed is using the Belgian date format (dd/mm/yyyy). I'm unable to change that unfortunately.

2 issues:

in case the dd is > 12, the import does not process the date
when dd <= 12, it does import them but for some reason it has an -2h offset. Probably some timezone issue, as the timezone is set to Europe/Brusssels, which is CET+2h

Is there a way to

preparse the dates somehow, to make sure the dates are available in a format that can be understood at all time (eg. yyyy-mm-dd)?
set the timezone somehow, so the feedme / craft knows the dates are being presented in CET+2h already?

EDITED

The timezone issue (second bullet) appears to be a known issue, see https://github.com/engram-design/FeedMe/commit/a923b67350341dcb17a628376bbb9ab4aa373780
This commit did not make it to a release yet (I'm using the most recent one 2.0.7 that doesn't contain this bug fix), if you use the codebase that is currently on the master branch this issue is fixed!
This leaves me with just 1 to go!

After being in contact with the developer both issues are solved. If you have a similar issue use the latest codebase on the master branch (not the 2.0.7 as that version doesn't have the fixes yet)

for the first issue (date format problem) there is an additional functionality available that allows you to predefine what the layout is of the date field you're trying to import

second issue (the date offset problem) was a bug and has been fixed

The most recent codebase can be found here: https://github.com/engram-design/FeedMe/archive/master.zip

A big thanks to Josh Crawford for helping out that fast!


How to change the locals name in Localized Sites I am developing multi-sites with the locals. Everything is fine. Is it possible to change the name of locals. I 'd like to give some other names to locals so that those can be more clear while managing the contents.

Please guide me for it.

You could add new pseudo localization files to Craft craft/app/framework/i18n/data/ and rename (translate) the name of your "language" and other things in these files.

I'd use en.php as a starting point and save it as en_custom.php. Then add a new key/value pair 'en_custom' => 'My Custom Country' to the languages array (line 205 ff.), which is responsible for the translation of the language names.


Start a Loop at the nth Entry in a Structure and Loop to the End? I'm trying to start a loop at the 8th entry in a structure and then loop through the remaining entries in that structure and stop once I reach the end. How would I accomplish this in Craft?

Using the offset parameter you can achieve this:

{% for entry in craft.entries.section('structureSection').offset(8) %}


Can't Upload JPEGs to live site (PEL error) I'm unable to upload any jpg/jpeg files to the server, it just comes up with an alert saying "upload failed". After checking the PHP error logs for Craft I found this error message is being created every time I try.

PHP Fatal error:  Class 'lsolesen\pel\PelConvert' not found in .../craft/app/vendor/lsolesen/pel/src/PelDataWindow.php on line 96

Any advice on how to fix this error?

I've tried:

Uploading different files to make sure it wasn't an issue with the one jpg
Uploading different file types (no errors occurred with other image file types)
Several local server fixes I found

@lindseydiloreto in the Craft Slack gave me the solution.

For some reason, the craft/app folder got messed up in the last update.

Re-downloading and replacing the /app folder fixed the problem


Get search results by relationship I have a section of "video" entries which are related to another section via an "area" field in the "video" section. When you do a search  on the front end by area then the related video displays as expected. What I also have in the area section is a text field full of postcodes, what I would like to happen is when you then do a search by postcode then the video displays that is related to that area, is that possible?

Here is my code that works for searches by area:

{% set query = craft.request.getParam('search') %}
{% set searchEntries = craft.entries.search(query).order('score') %}

{% for entry in searchEntries.video(':notempty:') %}
  {% set video = entry.video %}
  {{ video.embed({ width: 340, height: 191, showinfo: false }) }}
{% endfor %}

Do another call to craft.entries when you loop through the "area" entries and include the section and relatedTo params:

{% for entry in searchEntries %}
    {% set videos = craft.entries.section('videoSectionHandle').relatedTo(entry) %}
    {% for video in videos %}
         {# Output video here #}
    {% endfor %}
{% endfor %}

If you're trying to maintain a one-to-one relationship it might make sense to limit the relation query to one result, and to include the first param to return the first (and only) result and not an array – then you can omit the nested for loop:

{% for entry in searchEntries %}
    {% set video = craft.entries.section('videoSectionHandle').relatedTo(entry).limit(1).first() %}
    {{ video ? #--Output video here--# }}
{% endfor %}

You can read more about the relatedTo param here, it's pretty powerful.


How do I sort and display event entries when each event can have multiple start times? I have two different event types in my Events channel. The first one is events and it is very straightforward: Title, Description, Date. The other one is films and it is a little more complex: Title, Description, Screening(s) - which is 1 or more Date/Time. (I am using a supertable to allow the user to add as many screenings as they would like).

I have it set up like this to keep the administration of the content as DRY as possible - as all screenings of a movie will share the same description, title and other meta data.

I need to display all of my events and film screenings in an agenda view - sorted by date. How do I accomplish something like this?

The problem, if it isn't obvious, is that screenings from films could be staggered amongst screenings from other films so a simple for loop doesn't do the trick. I need to get all of the events and screenings (an individual screening being an "event" in this case) into an array that I can sort.

Thank you for any ideas or tips ahead of time.

One thing you could do is have all screenings be Events, and then have Films be a type which contains the film's data, but use relationships to link to multiple Events which are the film's screening times. You could even have Events have two entry types: Events and Film Screenings (or something similar to this) so they could be displayed differently in the agenda view, and Film Screenings could link back to their parent Film entry.

Here's more information about using relationships and reverse relationships: https://straightupcraft.com/articles/introduction-to-relations-and-reverse-relations-in-craft-cms-with-examples

I'm not sure if this solution would fit your needs, but given my understanding of your issue, I think this is how I'd try to tackle it.


Is there a very very basic example of simply outputting PHP with a plugin to Twig? For arguments sake let's say I wanted a plugin that is a basic output:

<?php echo '
Hello World
'; ?>

So all I am wanting to output is that, and I want that output to be available via twig (ie: {{ helloworld }}

Not passing any information, not doing anything with the craft database, etc. Just very basic.

Have a look at plugin template variables. You can simply create a method in your plugins variable file that returns anything you want to the template, which would be accessible via {{ craft.myplugin.customVariable }}.

<?php
namespace Craft;

class MypluginVariable
{
    public function customVariable($someProperty = 'defaultValueIfNotDefined')
    {
        return 'Whatever you want!';
    };
}


Added Locale, matrix content not copied I am attempting to add a second locale to a site with existing content, much of that content in matrix fields.

Following the documentation for Setting Up a Localized Site, I have defined the locale, enabled all sections for this locale (and the original one), set up the configuration and the index.php files. What I have not yet done is mark any field as translatable.

What I was expecting is that entries in the new locale would be initialized with content from the original locale. And this has happened, except that the matrix fields have not been duplicated, so the entries in the new locale do not have any of that matrix content.

This is very similar to How do I get Matrix elements to copy their content across language Locales?. The answer there is "don't mark matrix fields as translatable", which I haven't done, so not sure why this isn't working for me.

Any clues?

This is definitely a bug in Craft.  Doesn't just affect Matrix, but any relational field as well (Assets, Users, etc.)

It's not an super-easy fix, but as a workaround, you can re-save the entry in the original locale (before making any edits in the new) and the content will get duplicated over.


How can I tap into onUserDelete? I'm currently building a plugin that uses a table that contains rows with an 'active' field set to 1.

If an admin deletes a user from the system, I want to change this value to 0.

I found an 'onUserDelete' event documented but can't work out where or how to use it.

Any help would be greatly appreciated!

EDIT UPDATED:

I now have this code in the init() function of my plugin controller but deleting a user does not seem to fire the code:

    parent::init();

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

        $userId = $user->id; // ???????

        $craft->memberships_membership->cancelMembershipById($userId);
    });

Any ideas?

From the documentation on events, they follow this pattern:

craft()->on('component.eventName', function(Event $event) {
    // ...
});

So in your example, it'd be something like this and you'd want to add it to your plugin's init() method in the main plugin class.

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

    craft()->on('users.onDeleteUser', function(Event $event) {
        $user = $event->params['user'];
        $userToTransferContentTo = $event->params['transferContentTo']
    });
}

The full list of available events and the parameters they have can be found here.


Is there a way to create a new image transform 'onAfterInstall()' of a plugin? As the title suggests, I would like my plugin to generate a new image transform automatically (with a few settings) when the plugin is installed.

The purpose is to avoid my plugin from crashing if a transform hasn't already been generated yet (or doesn't have the same handle names).

Thanks,

Mark

Have a look at the method actionSaveTransform in the AssetTransformsController.

The code you actually need for your onAfterInstall would be like this:

// Only create if it doesn't exist (by handle)
if (is_null(craft()->assetTransforms->getTransformByHandle($handle))) {
    $transform = new AssetTransformModel();
    $transform->id = $transformId;
    $transform->name = $name;
    $transform->handle = $handle;
    $transform->width = $width;
    $transform->height = $height;
    $transform->mode = $mode;
    $transform->position = $position;
    $transform->quality = $quality;
    $transform->format = $format;

    if(craft()->assetTransforms->saveTransform($transform)) {
        // Success
    }
    else {
        // Error
    }
}


How do I write custom model validators for my plugin that refer to other fields? I'm looking at this guide to writing custom validators:
https://experiencehq.net/blog/the-definitive-guide-to-validation-in-craft-part-5-custom-validators

However, this only allows code that refers to the current field.  The comparison validators exist so I know it's possible.  I want to do a CVV and credit card number validator that check against the credit card type, and also make some fields conditionally required.

In this example only the attribute itself is referred to:

public function validateUsername($attribute)
{
    $value = $this->$attribute;

    if ($value && strtolower($value) == 'spartacus') {
        $message = Craft::t("No, I'm Spartcus!");
        $this->addError($attribute, $message);
    }
}

How do I refer to another field in the model in my validator?

Looks like I can just refer to the other field name:

public function validateUsername($attribute)
{
    $value = $this->$attribute;
    $otherFieldsValue = $this->otherField;

    if ($value && strtolower($otherFieldsValue) == 'spartacus') {
        $message = Craft::t("No, I'm Spartcus!");
        $this->addError($attribute, $message);
    }
}


Steps for integrating an HTML design to a website page and managing its content from backend I am a beginner to Craft CMS. I have an HTML design for Craft integration. I need to covert this to a live URL page on my website. Also, I need to manage its content from the backend. I think we need to do something related to entries, but I don't know what part I need to do first and what to do second, etc. Can anyone please help for the steps needed for this?

Thanks in advance.

I would first suggest getting your static HTML site up and running with twig, then slowly adding dynamic elements as you learn more about Craft.

Start with two template files _layout.twig and index.twig. _layout.twig is the file that all pages will extend, so it will contain all your html meta, css, js, etc. Within the _layout.twig you can define areas that can have content injected into, so in the example below I have the 'content' block.

_layout.twig:

<!DOCTYPE html>

    <meta charset="UTF-8">
    <title>title</title>

      {% block content %}
         Content will go here, if no content found this message will display.
      {% endblock %}

We can then extend the layout from the index.twig page by defining the content area.

index.twig, accessible from yourdomain.com/index (or yourdomain.com)

{% extends '_layout' %}

{% block content %}

I love puppy dogs

Puppy dogs love me

{% endblock %}

After that, once you have created your first section you will be able to make your pages dynamic.

index.twig

{% extends '_layout' %}

{% block content %}

{{ entry.title }}

        {{ entry.body }}

{% endblock %}

In terms of creating sections and entries you will need to invest some time looking at the available resources then post here or jump on the discord server if you need help with specific things.


Dropdown field 'default' I have a field of the dropdown fieldtype, let's call it myDropdown.

myDropdown has a list of options, one of which has the "default" checkbox checked.

If I use a front-end form to submit a new entry, but the form does not contain the myDropdown field, will Craft insert the value designated as the the default into that field, or will it just leave the field empty?

Yes, if you don't include the dropdown field in your entry form, Craft will store the default value for that field, if one has been set. If no default value has been set, then the value will be null.


License alerts in sandbox site I just deployed a site (still under work) on a sandbox subdomain (https://sandbox.site-name.org/) and I am getting license problems alerts. Also, the site is user/password protected (Apache basic auth, htpasswd).
The complaining plugins are verbb\comments and craft\commerce. Is this normal? Should I worry? How can I get rid of those alerts?

According to "How License Enforcement Works" a subdomain with 'sandbox' should work fine without Craft complaining about your license.

Does it have a dev-sounding subdomain (e.g. ‘craftdemo’, ‘dev’, ‘local’, ‘loc’, ‘qa’, ‘test’, ‘testing’, ‘sandbox’, ‘stage’, ‘staging’, ‘uat’, ‘acc’ or ‘acceptance’)?

Try contacting support thru the Craft control panel about this. If it's not working properly, I think they can at least add your domain to an allowlist.


Templates with .twig extension Does anyone know how to make Craft by default use .twig extensions. It helps IDEs better understand Twig blocks. I have tried .twig and .html.twig but it doesn't appear to work by default.

I don't want to set up special configs for every template.

Craft does already support .twig as a template file extension option by default (see the defaultTemplateExtensions config setting docs). If you want to allow .html.twig as well, just open craft/config/general.php and add this to the config array:

'defaultTemplateExtensions' => array('html', 'twig', 'html.twig'),

(Note that this will only affect front-end templates. The Control Panel is locked to .html and .twig for plugins.)


Normalizing Keywords Bug The StringHelper::normalizeKeywords() doesn't work as I expected.

When I normalize überblick it leads to the expected result:

StringHelper::normalizeKeywords('überblick') -> ueberblick

But when I normalize ÜBERBLICK I expect it also to be ueberblick but it actually returns überblick.

It could be fixed by adding the missing ASCII mappings (e.g. 196 => 'Ae') to the StringHelper::getAsciiCharMap() method or converting the string to lowercase before replacing the characters in StringHelper::normalizeKeywords() on lines 358 - 362:

-> switch these two lines:

// Remove punctuation and diacritics
$str = strtr($str, static::_getCharMap());

// Normalize to lowercase
$str = StringHelper::toLowerCase($str);

This may be a bug, and is probably worth reporting to P&T.

However, it's very difficult (if not impossible) for them to account for every potential ASCII character mapping for every possible language. For that reason, there is a customAsciiCharMappings config setting, which you can use as a workaround.


How to use the same category group as a filter on multiple channel sections? I have two channel sections, each with only their own entry types. I've added the same category group field to both. I'd like to filter each channel's list of entries by the same category group.

So if you're on Channel Steve (for example) you could hit the Category B link and see all the entries in the channel tagged with Category B. Then the same for Channel Bob. The same Category B link would be there, but when clicked it would show only the entries in Channel Bob tagged with Category B.

The problem I'm running into is that each category group uses only one path and template, and I need n of them. It seems like it'd be easy enough to associate one path/categories with one template multiple times for each category group so the category variable would be available on each channel's template. I think this is the optimal solution.

Right now I'm making it work with URL segment sniffing, but that feels hacky.

So, how can you set up category filtering on multiple channels with the same category group?

I would use a dynamic route instead of the path and template assigned in the category group. If you want the urls to be /Steve/B and /Bob/B, the route would look like {tag}/{slug}. Then in the template, fetch the channel using tag, and the category handle using slug.

Fetching the category:

{% set category = craft.categories.group('categoryGroup').slug(slug).first %}
{% if not category %}{% exit 404 %}{% endif %}

Fetching the entries:

{% set myEntries = craft.entries.section(tag).relatedTo(category) %}


Entry Form: redirect not working I use a front-end entry form based on the official documentation (https://craftcms.com/docs/templating/entry-form), but after saving the entry, I am running in an error 404 on the entry page.

<input type="hidden" name="redirect" value="viewentry/{id}">

But if I replace the entry id with the slug in the browser (example.com/viewentry/example), then it works.

Try replacing {id} with {slug}. I guess it needs a slug, not an ID.


Styling unordered lists in Craft I realise this is very much a Redactor question, but was wondering if anyone has figured out how to apply custom classes to UL's and OL's in Craft using the formattingAdd options?

I've tried the following but it just won't apply to any unordered lists I create:

{
  tag: 'ul',
  title: 'Large list',
  class: 'large'
}

This doesn’t appear to be possible without a plugin. The formattingAdd will add additional options to the Formatting menu, but will not alter the behavior of any of the other buttons, and you can only set the tag properties to p, pre, blockquote, and h[1-6].

Another option might be to use a Matrix field with two block types: Text and List. Text blocks would have a Rich Text field, and List blocks would have a Table field with one column, plus a Dropdown field that specifies what the class should be. From your templates you would do this:

{% for block in entry.myMatrixField %}
    {% if block.type == 'text' %}
        {{ block.text }}
    {% elseif block.type == 'list' %}

            {% for row in block.myTableField %}

{{ row.myColumnHandle }}

            {% endfor %}

    {% endif %}
{% endfor %}

If you really want to keep all this within Redactor and go the plugin route, you can use our Redactor Clips plugin as a starting point.


How to model a multiple relation situation? I have a site that has these different types of content:

Candidates
Questions
Answers

So there's a list of questions, that have answers that are related to a candidate. I imagine the models look like:

Question

Question Info

Answers

relatedCandidate
relatedQuestion

Candidate

Candidate Info

The main question is is this the best setup for this particular situation? Or should  I have a matrix in Questions with all the answers and then a related field for the candidate and the answer?

While this works if the question section works on it's own, if I ever need to display candidates and then their corresponding answers, I don't know if I can run through the Questions' matrix field and find only that candidate's answer.

I think this is the best way to model the data, and it lends itself very well to how Craft work.

I guess the only reason to go with the Matrix approach instead, would be to ease how the information is published in the control panel. In some cases it might be easier to just publish one question with all the answers, instead of one question and all the answers seperately. But it's hard to say, not knowing the actual content and amount of data.

It would definitely be possible to go for the Matrix solution too, but it might be a bit more complex to use in your templates, and maybe less efficient. But again, depends on your actual case.


How can I place links at the bottom of the site? is it possible to place my privacy notice and cookies policy in the footer menu?  Is there one and how do I do it?

It's impossible to give step-by-step instructions since every Craft site is unique and built differently.

The front-end templates for your site live in the craft/templates folder on your server.  You can change the look and layout of your site by editing those files, which are a combination of Twig and HTML.  Thanks like JavaScript, CSS files, images and assets will typically live in your site's public HTML folder.

Here's a list of learning resources to help get you up to speed on Craft and some links at the end in case you need help finding a developer.

Craft Official Docs & Support

Craft CMS docs - The official Craft CMS documentation
Craft Slack group - The Craft development team is in Slack every day along with 6,000+ other Craft developers and users from all over the world.
Craft Stack Exchange - You obviously found this one, but it is generally the best place to ask "how do I" type questions.
Official support email at support@craftcms.com

Learn Craft

Mijingo Craft Tutorials - Mijingo is our official education and training partner. They have a number of excellent free and paid resources for Craft CMS & Craft Commerce. Ryan Irelan, Mijingo's founder, also offers customized training online or on-site.
Tuts+ Tutorials - Not official but very good and low cost (most are $9).

Professional Services

Partner Match - If you need implementation help for Craft, we can match you with one of our Craft Service Partners or Craft Experts. We work with enterprise level partners, freelancers, and everyone in between.


Append a string to the end of all rich text links I'm trying to append a string to the end of all rich text links. Is there an already existing plugin for this?

I found a way to use the RetconHTML plugin for what I wanted. I just utilized the Attr filter and it worked the way I wanted. I had to also remove the way Retcon would add spaces to appended strings.

{{ block.paragraph | retconAttr('a', { href : '?some_text' ~ entry.title|kebab }, false) }}

By including false, it adds to the already existing href, rather than overwriting it.


Craft Commerce 2: Subscription Payment Gateway I am working in Craft 3 with the Commerce 2 plugin. I am trying to create new subscription plan there. But I am not able to do so because I don't have any Payment Gateway Installed that supports subscription. I tried to find it in Plugin store but not luck.

Can anyone suggest me any Payment plugin that support subscriptions.

Thanks

According to the Commerce 2 docs, the only first-party gateway that currently supports subscriptions is Stripe.

Again, according to the Commerce 2 docs, the Stripe plugin is available for free on the plugin store.


Optimizing With Http2 In Mind My main config is Apache/Centos 7/WHM/Redis/OPCache/PHP7.1/MariaDb/PHP-fpm/Http2 and have optimized my server to a great degree.  It's a 32GB dedicated HexaCore.  I have worked really diligent to get the server optimized over the last few weeks and the state it currently is in, it's pretty dang fast.  Now so you know I am not tooting my own horn, I will preface by saying this, I am the furthest away from a server admin as anyone can be, but I get by.

My question is: When serving up an local asset like CSS (/style.css) over HTTPS it takes about 2 seconds longer to load. A big part is the time of 800+ms for the style.css to load over https, ugh. So I am asking how can I use http2 to my advantage with Craft? I want to run in HTTPS all the time but not with the handshaking lag. Any suggestions or examples would be greatly appreciated.

In case you are tempted to say go Nginx, I would love too but unless you are volunteering, at this time I cannot put myself through an Nginx install.

Thanks!

So... just to be clear. This /style.css is a static asset, it's not sitting in the craft/templates folder, right?

Assuming that's the case, something is definitely wrong if https is taking 2 seconds to load it. Sounds like something with your server is misconfigured.

How are you measuring this, exactly?


How can I display dateUpdated for the most recent updated entry in a category? I would like to display the date that the site was last updated. This date is the same as the last entry added to a specific category. Thanks in advance.

You can order entries by dateUpdated in descending order and then get the first entry. You would use that entries dateUpdated field to show when the site was last updated.

{% set entry = craft.entries.order( 'dateUpdated desc' ).first() %}
{{ entry.dateUpdated }}


Image Transforms - disable scaling up I have image transforms set up and working well for my site, however I have an issue that seems to be a possible feature request because it is not documented or on this Stack Exchange.

If a user uploads an image that is smaller than the image transform setting, it scales the image up for them to the specified size. However this results in a pixellated image because of the upscale. What I would like to be able to do is only scale down images to the respective transform values, but if smaller, then keep their size, thus avoiding the pixellation and extra unnecessary file size.

Any tips?
Thanks in advance.

Seems like the only option at the moment is to follow this post's technique:

Prevent Asset Transforms from scaling Image past 100%

Hopefully it will be implemented in the CP in the future... according to this feature request:

https://plus.google.com/110881688132908256910/posts/FAzrGAJ99W7


Setting an entry slug from a pluign I have a plugin where I'm creating custom entries based on user submitted data. Saving these entries works well. As does modifying their titles after saving to add the entry's ID to the title (using craft()->on('entries.saveEntry', function(Event $event) { ... }). The problem I'm having now is that I'd like to also update the slug at this point, so that each entry's slug is just its ID.

I've tried using:

$entry->setContentFromPost(array(
    'slug' => $entryId,
));

and

$entry->getContent()->slug = $entryId;

but neither do anything — even though the title change is getting saved successfully. Either I'm missing something, or the slug is handled differently than both entry fields and entry base content.

My question: How do I update the entry slug from a plugin to be just the entry's ID?

Here's the code I currently have in my plugin's base class:

public function init()
{
    craft()->on('entries.saveEntry', function(Event $event)
    {
        $entry = $event->params['entry'];
        $entryId = $entry->id;

        $newTitle = str_replace('Name: ', $entryId . ' - ', $entry->title);

        $entry->getContent()->title = $newTitle;

        $entry->setContentFromPost(array(
            'slug' => $entryId,
        ));

        // Here I use elements->saveElement() because using entries->saveEntry
        // cased an infinite loop.
        // It would be great to have this sanity checked as well, please :)
        craft()->elements->saveElement($entry);
    });
}

If you set the slug directly on the entry element, it should work!

public function init() {
    craft()->on('entries.saveEntry', function(Event $event) {
        $entry = $event->params['entry'];
        $entryId = $entry->id;

        $newTitle = str_replace('Name: ', $entryId . ' - ', $entry->title);

        $entry->getContent()->title = $newTitle;

        $entry->slug = $entryId;

        craft()->elements->saveElement($entry);
    });
}


Empty date field becomes today's date I have a date field, and I want it to be possible for this to be empty. How it works now is that if you don't enter a value, it takes today's date. Any suggestions?

That happens because the date filter returns the current date for null values / empty strings.

  If the value passed to the date filter is null, it will return the current date by default.

To work around this, you would add a conditional.

{% if entry.myDate %}
    Date: {{ entry.myDate|date('Y-m-d') }}
{% endif %}

Another way to do this is to use a ternary operator.

{{ entry.myDate ? entry.myDate|date('Y-m-d') }}


Duplicate an existing Order as a new Cart in Commerce Orders can not be edited in Commerce. Makes sense.

What we want to do however is make it very easy for someone to re-order a previous order. So for example they've had an order that contains "two pairs of socks, two pairs of pants, toothpaste, and soap" but they need all of that again as a new order.

Rather than manually having to do so, we want to offer a "re-order" button.

Given that an order is just a cart that's been marked complete, we're thinking it should just clone the order into a new cart, so they can review it and make any amends they need to, then just continue as normal with the checkout process.

I can not figure out how to do this though. Getting the Order is simple enough, and there's an existing cart set up too. But how would I punt that old Order into the new cart?

Using the MultiAdd plugin, you can do the following on the order page:

<form method="POST">
    <input type="hidden" name="action" value="multiAdd/multiAdd">
    <input type="hidden" name="redirect" value="commerce/cart">
    {{ getCsrfInput() }}
    {% for item in order.lineItems %}
        {% set itemNumber = loop.index %}
        <input type="hidden" name="items[{{ itemNumber }}][qty]" value="{{ item.qty }}">
        <input type="hidden" name="items[{{ itemNumber }}][note]" value="{{ item.note }}">
        <input type="hidden" name="items[{{ itemNumber }}][purchasableId]" value="{{ item.purchasableId }}">
        {% for key, option in item.options %}
            <input type="hidden" name="items[{{ itemNumber }}][options][{{ key }}]" value="{{ option }}">
        {% endfor %}
    {% endfor %}
    <input type="submit" value="Order Again" />
</form>

This adds a "Order Again" button with the same products and quantities, but options may be bit more difficult to sort out.


How can I set new user accounts to pending status in a Craft 3 module? I have the following code in my site module:

Event::on(
    User::class,
    User::EVENT_BEFORE_SAVE,
    function (ModelEvent $event) {
        /** @var User $user */
        $user = $event->sender;
        if ($event->isNew === true) {
            $user->pending = true;
        }
    }
);

It was working as expected until I updated from Craft 3.0.25 to 3.0.27.1

I think this issue is related to a change in the src/controllers/UsersController.php file as per GitHub https://github.com/craftcms/cms/commit/db089251994329d0fbe082c0d3ff234a01d82c98

Also, I replaced my 3.0.27.1 UsersController.php with one from a 3.0.25 install, and my code works again.

What is the best/correct/official way to set new user accounts to pending status in a module that won't break with future Craft updates?

I tried this:

Event::on(
    Users::class,
    Users::EVENT_BEFORE_ACTIVATE_USER,
    function (UserEvent $event) {
        $event->isValid = false;
    }
);

but got There was a problem activating the user. when trying to activate the user account.

P.S: Verify email addresses? is disabled in User Settings.

Yeah you’re correct that db089251 is the culprit here, which fixed a bug where user activation events weren’t getting fired when users were first created, if the “Verify email addresses?” setting was disabled.

Your new code is close, but that is going to get called each time Craft tries to activate a user—both when they are first created, and when you try to manually activate a user later on. So you just need to add a condition to your event handler.

As a starting point, maybe just check if it’s a site (front-end) request.

Event::on(
    Users::class,
    Users::EVENT_BEFORE_ACTIVATE_USER,
    function (UserEvent $event) {
        if (Craft::$app->request->getIsSiteRequest()) {
            $event->isValid = false;
        }
    }
);


Simple Module in Craft CMS 3 How do I create a simple module for one website in Craft?. I don't have much experience in Craft CMS.  I have tried from 3 days but I cannot get an answer. I'm following all the tutorials that I can find, but none I feel are clear. Any recommendations on the simplest of examples, even if it's just outputting a variable.

Start with the manual: https://docs.craftcms.com/v3/extend/module-guide.html

This blog post covers module development in more detail:
https://nystudio107.com/blog/enhancing-a-craft-cms-3-website-with-a-custom-module

It includes a link to generate a scaffold module, which should work out-of-the-box.


Save a selected category for a user (using a plugin) I have some categories, and with the use of a category field a user can select these from within his / her profile.

Which is shown in the image:

In my Twig template I can get the user selections out using the following code.

{% set property_prefs = craft.categories({
    relatedTo: { sourceElement: currentUser, field: "propertyPreference" },
    limit:     null
}) %}

But what I want to know is how can I programmatically save a user selection using the API from within my plugin.

Also, which table are these stored in?

I had to do something similar to this in a plugin recently, Inserting Relationship Into Entries Field - Plugin Not Saving Relation, I know it's users to an entry field but I would assume the methods are similar.

So you will need 3 things in order to save a users categories

1. The Craft\FieldModel of the field which has the associations

$field = craft()->fields->getFieldByHandle('propertyPreference');

2. The source, in this case the matrix block that has the field

$source = craft()->matrix->getBlockById(<someId>);

3. An array of element id's you wish to relate to the field

$relations = $user->propertyPreference->ids();

Once you have those you can edit the $relations array however you see fit and then simply save the relations back

craft()->relations->saveRelations($field , $source, $relations);

You can find out more about the save relations function in the class reference

As for which table, I would assume they are in craft_relations


Custom CP Element Indexes I'm working on a custom Craft 3 site, and I need to be able to configure the element indexes within the control panel for a few of my custom EntryTypes. There's two particular things I'd like to control (which may merit two separate answers):

I'd like to be add custom columns to the table. These columns do not correspond to fields on the Entry, but they're more of a "computed property" if that makes sense.
I'd also like to modify the query that is ran for fetching those entries. In my particular case, some entries should not show up based on which user is logged in, and some custom business logic.

Is there a way to do this? My current investigation with ElementIndexesController::actionGetElements (the API call that the CP appears to be making) hasn't panned out: I don't see any global events or view hooks that I could wire into.

For the second part of your question, look into Element Sources. You might be able to pull off  something fancy in a module, where certain users have access to different sources.
For the first part of your question, look into the EVENT_REGISTER_TABLE_ATTRIBUTES and EVENT_SET_TABLE_ATTRIBUTE_HTML events. Here is a rough example of how it will look...
// Add index table attributes
Event::on(
    Entry::class,
    Element::EVENT_REGISTER_TABLE_ATTRIBUTES,
    static function(RegisterElementTableAttributesEvent $event) {

        $event->tableAttributes['computedColumn'] = ['label' => 'Computed Column'];

    }
);

// Modify index table display values
Event::on(
    Entry::class,
    Element::EVENT_SET_TABLE_ATTRIBUTE_HTML,
    static function(SetElementTableAttributeHtmlEvent $event) {

        /** @var Entry $entry */
        $entry = $event->sender;

        switch ($event->attribute) {
            case 'computedColumn': // How to identify a computed column
                $event->html = 'any valid HTML';
                break;
            case 'field:101': // How to identify a normal field
                $event->html = 'whatever you want it to be';
                break;
        }

    }
);


Wrap each line with a span tag Following situation:

I have a inline-block title with a background gradient applied. So in order that the background always starts from the left, each line will have to be spanned by a span tag.

Welcome to

our site

should become this:

Welcome to

our site

I've started with this:

{{ block.heroTitle|nl2br }}

But I'm stuck.
Any help appreciated.

You can split your text

{% set text = block.heroTitle|nl2br %}
{% set splited = text|split('
')%}
{% for part in splited %}
    {{ part }}
{% endfor %}

If you need you can use the trim filter as well

{{ part|trim }}