Looping Entries Based on Field State I'm pretty new to Twig and I know the level here is far above my question, but thank you in advance...

I'm designing a site with sponsor logos on the homepage, each sponsor is an entry in a channel of sponsors. I have a lightswitch field on the entry page called 'showOnHome'.  I've tried "if" statements and conditionals in the loop, but have only got to where it shows the first entry and breaks the loop.

The following works to get all of the entries,

    {% for entry in craft.entries.section('sponsors') %}
        {% for image in entry.sponsorlogo %}

<img src="{{ image.getUrl() }}" alt="{{ image.title }}"

        {% endfor %}
    {% endfor %}

How do I only get entries where showOnHome == '1'?

Thank you in advance for helping the rookie.

{% for entry in craft.entries.section('sponsors').showOnHome('1') %}

The .showOnHome('1') restricts your query to ones with the lightswitch on.

If you wanted only the ones with the lightswitch off, you would use .showOnHome('not 1')


"An unknown error occurred." appears when I try to log into Craft's admin using browsersync's proxy mode I've stumbled upon a weird thing.

When I run browsersync as browser-sync start -p localhost:8000 and try to log into Craft's admin at localhost:3000/admin I get the message "An unknown error occurred."

If I enter the wrong password, nothing at all appears nor happens.

This can be worked around by logging in once at localhost:8000/admin, and then accessing the proxied version after... But I'd be sweet if I could login through the proxied version :)

Any suggestions on how this can be resolved?

Here's the log generated once I've deleted all the contents of the logs and then press the login button: http://pastebin.com/3LjbQLj0

Forgot about this question!
I've since solved it by using a different approach.

Now I'm injecting the broser-sync script via its config, avoiding injection if the url is '/admin/', and redirecting to :8000 if '/admin/' is visited from :3000

Here's my whole working browser-sync.js config file, for those few other souls searching for something similar:

Note: I'm auto-injecting the webpack dev build with this config as well.

const sync = 3000
const script = 'browser-sync-client.js'

const php = 8000
const webpack = 1337
const adminPath = '/admin/'
const address = require('ip').address()

module.exports = {
    port: sync,
    proxy: {target: `${address}:${php}`},

    files: [
        'source/layout.twig',
        'source/pages/*.twig',
        'source/components/*.twig'
    ],

    ui: false,
    open: false,
    notify: false,
    ghostMode: false,
    socket: {clientPath: ''},

    logLevel: 'info',
    logPrefix: 'Browser-sync',

    watchEvents: ['change', 'add'],

    rewriteRules: [
        {match: /<\/head>/i, fn(request, result, match) {
            return `<script src="http://${address}:${webpack}/build.js"></script>` + match
        }}
    ],

    snippetOptions: {
        ignorePaths: adminPath + '*',
        rule: {
            match: /<\/body>/i,
            fn(snippet, match) {
                return `<script src="http://${address}:${sync}/${script}"></script>` + match
            }
        }
    },

    middleware: [function(request, result, next) {
        if (request.url.startsWith(adminPath)) {
            result.writeHead(301, {Location: `http://${address}:${php}${request.url}`})
            result.end()
        } else {
            next()
        }
    }]
}


Using XMLReader With Plugin In my project, I have a reference to XMLReader in a plugin; however, I get this error message:

Class 'Craft\XMLReader' not found

Here is the code which calls it:

$reader = new XMLReader();

Can XMLReader be used within Craft, or can there be a customization which would allow it?  Thanks

You need to be in the correct namespace try

$reader = new \XMLReader();

Like here


Live Preview only works with published entries We have a site where Live Preview only works with entries that have been previously published. When trying to preview entries we're working on (or drafts), we see either the latest entry for that section instead - or sometimes the correct entry template but with other/missing data in it.

Puzzled as to what is going on. There are no console errors.

My understanding is you have to save an entry first before you can use live preview.

Brandon says as much in his answer here as well:
https://craftcms.stackexchange.com/a/12091/103


Where can I edit the "Service Unavailable" page/template? Sorry if this is an obvious thing - can't seem to find an answer in the docs.
Where can I edit the system offline message? "service unavailable"

Try creating a 503.html file at the root of your templates folder. This should override the default template located at craft/app/templates/503.html.


Craft 3: Environment variables are not parsed when used in Assets source field I'm using Craft 3 and I have 2 Sites setup.

In my config/general.php file I have:

return [
    '*' => [
        'environmentVariables' => [
            'baseAssetsUrl' => '//'.strtolower($_SERVER['SERVER_NAME']).'/assets/',
            'baseAssetsPath' => realpath(dirname(__FILE__)).'/../web/assets',
        ],
    ],

    'craft3uk.dev' => [
        'timezone' => 'Europe/London',
        'siteUrl' => 'http://www.craft3uk.dev/',
    ],

    'craft3me.dev' => [
        'timezone' => 'Asia/Dubai',
        'siteUrl' => 'http://www.craft3me.dev/',
    ],

    'dev' => [
        'devMode' => true,
    ],

    'staging' => [
    ],

    'production' => [
    ],
];

I can access the variables fine in a template like:

{% set baseAssetsUrl = craft.app.config.general.environmentVariables.baseAssetsUrl %}
{% set baseUploadsUrl = craft.app.config.general.environmentVariables.baseUploadsUrl %}

But when I try using {baseAssetsPath} like this

I get:

I'm a bit confused as I have a Craft 2 site setup the exact same way and this works fine.

I cannot see anything in the Craft 3 docs regarding this either?

Can anyone help me out please?

Environmental variables as such don't exist "as a thing" in Craft 3. Instead, you'd define your Volumes in the AdminCP and override anything you need in craft/config/volumes.php

You can see an example of how to do it here: Craft 3 Multi-Environment


Craft pro test environment expires? Can no longer access test environment Can someone please help or advise me (I'm just starting to learn about Craft and setting up local servers. Sorry if this is a silly question).

I set up Craft Pro locally using MAMP. It worked yesterday just fine, but this morning I'm not able to access the admin side unless I go to "localhost:80", (localhost:8888 worked yesterday, but doesn't today. Is says it can't connect).

And even then, it's asking me to upgrade my license: "You’re running Craft Pro with a Craft Personal license, downgrade/upgrade." I thought that as long as you were running things locally it's ok to continue with the pro test version? Does the test environment have an expiry?

Thank you.

Are you using MAMP or MAMP Pro? If it was running on a different port yesterday (8888), then it sounds like you might have multiple installations. Try going over the additional resources posts here to verify your installation.

  "You’re running Craft Pro with a Craft Personal license, downgrade/upgrade."

Try clearing your craft/storage/runtime/cache folder.


Using FeedMe with the instagram API Just downloaded FeedMe, and it seems like a great solution to what I want to do, but I can't get it to succesfully run a json import on a feed generated by instagram. When I hit 'Save and Continue', I get a PHP warning:

file_get_contents(): php_network_getaddresses: getaddrinfo failed: nodename nor servname provided, or not known

It's on this line:

 public function getRawData($url)
     {
     if (file_get_contents(__FILE__) && ini_get('allow_url_fopen')) {
         $content = file_get_contents($url);
     } else if (function_exists('curl_version')) {
         $curl = curl_init();
         curl_setopt($curl, CURLOPT_URL, $url);
         curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
         $content = curl_exec($curl);
         curl_close($curl);
     }

     return ($content) ? $content : false;
 }

It's worth noting, I have no idea what to set the Primary Element as. Didn't see any documentation for JSON on the readme

Sounds like a server (DNS) configuration issue. PHP can't open the URL because it can't resolve the domain.


How can I print the name of every template being rendered in HTML comments, when in devMode? Is there a plugin or setting that prints the name of every template being rendered in HTML comments? I noticed this type of feature in a Drupal project and it was useful for debugging.

This is useful if you add it to every template you make, but I'd like to be able to turn it on/off globally for all templates in dev mode:
How can I make a template output its own filename?

So this sounded like a fun problem to solve... so I wrote the Template Comments plugin that does what you want:

This free plugin adds a HTML comment to demarcate {% block %}s and each Twig template that is included or extended.


Back-end validation of product variant I'm creating a product page for a product with multiple variants. In this case the variant represents a different size (with unique SKU, stock, etc..).

It's laid out like so (don't mind the ugly styling):

I don't want to pre-select a size option because I want to avoid people adding the wrong product to their cart.

In the template there's a hidden field with the purchasableId of the variant. The value attribute starts empty and when people click one of the options it is set to the corresponding id.

<input type="hidden" name="purchasableId" value="">

However, when people click 'Add to cart' right away, without selecting a size the following Craft\Exception is shown:

Not a purchasable ID

How can I customize this error message to notify the customer that they have to select a size option?

I could of course solve this problem by using javascript but that doesn't seem very solid to me. So is there a way of validating the stuff added to the cart in the back-end and getting something like a JSON response?

Well, if you submit to your add to cart form via ajax, you will already get a json response - with an error - you can simply grab that error, test for Not a purchasable ID and then change the text to whatever you want.

If you're submitting in a non ajax fashion, you won't get a JSON response no matter what clearly.

I agree with the comment above - I'd generally handle this in front end JS, by disabling the add to cart until a size is selected.  And I guess if you're allowing your site to use no-js, then in that case I would probably just pre-select the most popular option (Medium, presumably).

You can also write a plugin that listens to https://craftcommerce.com/docs/events-reference#commerce_cart.onbeforeaddtocart and does whatever validation you need, and returns a response any way you want, including via JSON (i.e. $this->returnJson(["success"=>true]); or e.g. $this->returnErrorJson($errors); where $errors holds your validation errors...)


MSSQL Support for Craft? Is there a MSSQL support for Craft CMS?
Or any plugin that can help to connect to a MSSQL database?

Thank you!

Assuming you're running Craft CMS 3, the Connect plugin will let you connect to MSSQL databases (local or remote)

You'll just need to do:

composer require yiisoft/yii2-mssql

...on your Craft CMS project. To be clear, this doesn't add support for MSSQL to Craft itself, it just lets you query MSSQL databases in your Twig templates.


How Do I Select the second instance of a certain block type We use a matrix field for the article content on our site. We have different blocks for different content (text, images, embed etc..) and we have optional fields that are outside of the matrix that  only need to be defined once, like a related article or place.

My current code to output the matrix is as follows

{% for block in entry.postBody %}

{% include 'blog/blocks/_' ~ block.type ignore missing with {"block":block} only %}

{% endfor %}

I want to float my related related restaurant section (which is optional) after either

the second instance of a text block

or

the last text block.

Some of my blocks are elements that take up the entire width of the section, so I want to attach it to a text block so that it floats neatly alongside the text.

How would I select the second or last instance of a certain block type within my for loop?

You could save that second text block's ID to a variable and compare against that in your text partial:

_entry.html:

{% set textBlocksIds = entry.postBody.type('text').ids() %}
{% set secondTextBlockId = textBlocksIds|length >= 2 ? textBlocksIds[2] : textBlocksIds[1] %}

{% for block in entry.postBody %}
    {% include 'blog/blocks/_' ~ block.type ignore missing with {
        'block': block,
        'secondTextBlockId': secondTextBlockId
    } only %}
{% endfor %}

blog/blocks/_text.html:

{% if block.id == secondTextBlockId %}
    {% include 'blog/partials/_restaurants' %}
{% endif %}


Adding dynamic second email address to Contact Form plugin According to the Contact Form plugin docs, I can do:

<input type="hidden" name="toEmail" value="{{ 'name@domain.com, name2@domain2.com' | hash }}">

That seems to work fine, but one of those email addresses I want to add dynamically. I've tried the following, but none seem to work, generally sending to just the second email address:

{# adding first email as var #}
{% set firstEmail = 'name@domain.com' %}
<input type="hidden" name="toEmail" value="{{ firstEmail ~ ', name2@domain2.com' | hash }}">%}

{# adding first email as var and avoiding | hash #}
{% set firstEmail = 'name@domain.com' %}
<input type="hidden" name="toEmail" value="{{ firstEmail ~ ', name2@domain2.com' }}">%}

{% set firstEmail = 'name@domain.com' %}
{% set emails = firstEmail ~ ', name2@domain2.com' %}
<input type="hidden" name="toEmail" value="{{ emails | hash }}">
{# RESULT: <input type="hidden" name="toEmail" value="505103f2971d445c709c131b8eee0a59e3ff668bname@domain.com, name2@domain2.com">#}

{# adding first email as var with extra quotes #}
{% set firstEmail = 'name@domain.com' %}
{% set emails = "'" ~ firstEmail ~ ", name2@domain2.com'" %}
<input type="hidden" name="toEmail" value="{{ emails | hash }}">
{# RESULT: <input type="hidden" name="toEmail" value="e3a44b3632212521351d8d44af34742a63f6516e'name@domain.com, name2@domain2.com'"> #}

Any ideas?

Both, the example from the Contact Form docs

{{ 'me@example.com,me2@example.com'|hash }}

...and the 3rd example snippet in your question

{% set firstEmail = 'me@example.com' %}
{% set emails = firstEmail ~ ',me2@example.com' %}

{{ emails|hash }}

...output exactly the same string for me! So I think you have to search for an answer to your issue elsewhere.


How do I query for all users that bought a license? I’m trying to use Craft Commerce with the Digital Products plugin for a site where users can pay for being listed on that site.

Therefore I need to query for all users with certain criterias plus a valid license.

I’m not sure how to tackle this. I tried something like this, but it doesn’t work.

{% for user in craft.users({
    group: 'profiles',
    relatedTo: craft.digitalProducts.products({type: 'access'})
}) %}

Another approach would be to list all licenses, collect the related users and then list them. But that doesn’t seem like a good idea either, in terms of performance.

Any hint is much appreciated.

I don't think it's currently possible in as clean as manner as you'd like. I'd tackle the problem by writing a small plugin that queries the database and returns a list of user ids that match the criteria.

Remember, though, is that a license does not necessarily have a user id attached to it - a license must have either a user id or an email assigned to, so you might want to keep that in mind.


Does deleting an original asset but keeping the transform folder asset make Craft replace the original file with the biggest transform? I have a client who has uploaded many giant images to the CMS (8mb+). I'd like to free up that space now that those image have been transformed to more web-friendly sizes. Is it safe for me to delete the original files stored on the server or does Craft require those to create new transforms?

Does deleting an original asset but keeping the transform folder asset make Craft replace the original file with the biggest transform?

No - Craft will always use the originally uploaded asset as the "source of truth" for generating new transforms.
You can, however, replace the originally uploaded 8mb+ file with a smaller one, and it'll be used as the source of truth for generating new transforms.


Website taking 30+ seconds to load One of my Craft websites is taking a long time (30+ seconds) to load. The /admin area also loads slowly. I have other installs of Craft on the same server that don't experience this problem.

Are there any debugging tools built into Craft to see which part of the site is taking the long time to load?

Some server information:

DigitalOcean instance in SF with 2GB ram
Nginx 1.6.0 (set up through Forge).
PHP 5.5.12-2

I have tried a couple things:

Disabling gzip (I recently enabled it)
Restarting the server
Changing the mysql connection address from localhost to 127.0.0.1 (also tried server IP)
Enabling memcached as the cache type
Clearing cache/rebuild assets/reindex search

The error logs don't show anything unusual.

There is a reasonable chance that this is due to a specific plugin.

Try disabling all of your plugins, and see if the site is loading quickly again. If it is, try re-enabling each plugin one by one, to determine which of them may be causing the slowdown.

It's important to remember that your plugins actually get loaded on every single page load, both front-end and back-end.


Load currentUser using Sprig with Blitz I'm having an issue with Sprig + Blitz Caching. I'm trying to load a user image if currentUser exists, though I'm having an issue with the caching. Sprig is loading in the unregistered user photo when logged in. I'm unsure if it's setup right.
      {{ sprig('components/_componentUser', {}, {
        's-trigger': 'refresh, load'
      }) }}

Then in my _componentUser
  {% if currentUser %}

            {% else %}

  {% endif %}

Duplicate of https://github.com/putyourlightson/craft-sprig/issues/118
The code is correct and what you are experiencing is likely due to local browser caching.


Save matrix block to new entry in plugin I have been trying two separate methods to accomplish and both keep resulting in the same errors no matter what I try.

The entry I am saving has a few fields the last of which is a matrix block (I am able to save the entry fine when not trying to save the matrix field to it.). This matrix block has two entry field types and the last field is a table field. I do not need to save actual data to these fields; it's fine that they are null/empty. I made sure that in the matrix block settings for these fields are not marked as required.

I am testing this via ajax calls in jQuery.

First Method (described here):
Craft sends back an error stating that...

Argument 1 passed to Craft\MatrixService::validateBlock() must be an instance
of Craft\MatrixBlockModel, array given, called in
/path/to/project/app/fieldtypes/MatrixFieldType.php
on line 393 and defined

It appears to me that craft is expecting a matrix block model not an array. But even Brandon Kelly shows an example here of this method working...so what am I doing wrong..?

Here's my code:

private function _buildEntry ($college, $now, &$data) {
    $entry = new EntryModel();
    $matrixData = array();
    $entry->sectionId = 4;
    $entry->authorId = 1;
    $entry->typeId = 1;
    $entry->enabled = 1;
    $entry->getContent()->title = $college->collegeName." ".$now;
    $entry->getContent()->timeEntryStartDate = $now;
    $entry->getContent()->timeEntryCollege = array($college->id);

    //set up the matrix data
    $matrixData['new1'] = array(
        'type'      => 'weekBlock',
        'enabled'   => true
    );

    $entry->getContent()->timeEntryWeek = $matrixData;

    //save the new entry
    $success = craft()->entries->saveEntry($entry);

    if(!$success){
        Craft::log('Could not save the entry "'.$entry->title.'"', LogLevel::Error);
    } else {
        Craft::log('Saved the entry! '.$entry->title.'"', LogLevel::Error);
    }
}

Second Method (described here): Craft sends back an error stating that...

Trying to get property of non-object

My code for this second part which I call after craft successfully saves the entry (which works fine)

public function actionTest($id = 3) {

    $block = new MatrixBlockModel();

    $block->fieldId    = 20; // Matrix field's ID
    $block->ownerId    = 178; // ID of entry the block should be added to
    $block->typeId     = 6;
    $block->getContent()->setAttributes(array(
        'timeEntryHouse' => array(183),
        'timeEntryEmployee' => array(1),
        'timeEntryDays' => null
    ));

    $success = craft()->matrix->saveBlock($block, false);
    if (!$success)
    {
        Craft::log('Couldn’t save the entry "'.$id.'"', LogLevel::Error);
    } else {
        $this->returnJson('worked');
    }
}

ok just found out the answer to the second method. I was using the incorrect typeId apparently. I wasn't able to find this in any of the error logs, so this was just luck.

To make sure you get the correct typeId do so in this way:

$matrix = craft()->fields->getFieldByHandle("fieldHandle"); //look in craft_fields table
$matrixBlocks = craft()->matrix->getBlockTypesByFieldId($matrix->id);

You can iterate through $matrixBlocks and look at each blocks id but in my case I knew there was only one block so I just accessed the id like this

$typeId = $matrixBlocks[0]['id'];


Can I call a filter on all Rich Text fields? I'm looking to dynamically replace the ℠ glyph with SM in all rich text fields, since that glyph doesn't exist in the font we're using. I'd like to avoid having to call the |replace filter on every field in every template, and I can't seem to get the customAsciiCharMappings general config setting to work either (I'm not sure if I really understand what it does). Does Craft have something like a global replace function/filter?

customAsciiCharMappings won't help you here.

There is the "Find and Replace" tool available to admins (Settings->Tools) in the Control Panel, but its' a one-off thing and searches/replaces against all textual field types (Plain Text, Rich Text, etc. both inside and outside of Matrix fields).

Honestly, probably just create a small Twig macro that wraps |replace and use that wherever you're outputting Rich Text fields on the site.


craft-imageoptimize plugin cropping position I am using imageoptimize plugin to crop images, but I am unable to find cropping position setup in a template.

{% set optimzedImages = craft.imageOptimize.createOptimizedImages(
       entry.backgroundImage.one(),
          [
                    {
                        'width': 1440,
                        'useAspectRatio': true,
                        'aspectRatioX': 1.0,
                        'aspectRatioY': 0.35,
                        'retinaSizes': ['1'],
                        'quality': 82,
                        'format': entry.backgroundImage.one().extension,
                        'position' : 'top-center'
                    }
                ]
            ) %}

The above code is cropping image in center-center and I want to crop an image from top to aspect ratio height.

FWIW, I would not recommend doing image resizing via your Twig templates, because it will do them on page load time. Rather, I’d recommend doing them via an Optimized Images field as per: https://github.com/nystudio107/craft-imageoptimize/blob/v1/README.md#dynamically-creating-optimized-image-variants

But if you really want to do it, the parameter there is the same as you’d use for regular Craft transforms: https://docs.craftcms.com/v3/image-transforms.html#defining-transforms-in-your-templates

So you could do 'top-center' or such

But especially since you’re just creating one image variant, there’s no real advantage to doing this via ImageOptimize in your templates. Just use a regular Craft transform. With ImageOptimize installed, the resulting image will be optimized when done via Craft transforms, too.

The real benefit of using ImageOptimize to create image transforms is to make creating responsive image srcsets easier.


Craft 3 Controller giving 404 Updating a plugin to Craft 3 (also changed its name). I know this is probably something very simple, like capitalization, but can anyone point out what's wrong?

Firefox console shows a 404 for
http://f.test/index.php?p=admin/actions/dryCalendar/calendarOccurrencesField/generateAjaxMiniCalendar
and then
Type error: Response is null

So perhaps Craft is getting the request, but $this->returnJson($response); isn't terminating the request, i.e. Craft continues to try to find a page to match?

My files are set up like this:

DryCalendar.php
controllers/DryCalendar_CalendarOccurrencesFieldController.php

is

<?php
namespace Craft;
//namespace kr37\drycalendar\controllers;
use Craft;
use craft\base\Controller;
class DryCalendar_CalendarOccurrencesFieldController extends BaseController
{
    public function actionGenerateAjaxMiniCalendar() {
        ...
        $this->returnJson($response);
    }
}

and in my Garnish js is

Craft.postActionRequest(
    'dryCalendar/calendarOccurrencesField/generateAjaxMiniCalendar',
    data,
    function(response) {
         ...
    });

Thanks for any help!

Craft 3 action routes are snake-case rather than camelCase thus your route needs to be plugin-handle/controller-handle/function-name instead of pluginHandle/controllerName/functionName

Your Controllers namespace must be prefix\namespace\name\controllers so in your case it could be kr37\drycalendar\controllers not Craft.

Furthermore you don't need to include your plugin name to the classname anymore. Your controller name can be

CalendarOccurrencesFieldController

Your action will then be drycalendar/calendar-occurrences-field/generate-ajax-mini-calendar

Keep in mind you'll have to create routes of you don't use the action parameter in your request. Currently you are trying to access your controller via cp/site route, not via action route


Do I use Twig filters 'include' and 'extends' for localized site correctly? I use regular file names for template structure from documentation for clearer understanding.

I have the template structure:

_layouts

base.twig

_includes

header.twig
body.twig
foot.twig

index.twig
de

_includes

header.twig
body.twig
foot.twig

index.twig

So for top level domain, 'index.twig' extends 'base.twig' and 'base.twig' include 'header.twig','body.twig' and 'foot.twig'.

For sub level domain (example.com/de), It's the same scenario as for top level domain.

All 'index.twig' files in all sub level domains extends the same file located at '_layouts/base.twig'.

The include filters look like this in my 'base.twig' template.

{% block header %}{% include '_includes/header' %}{% endblock %}
{% block body %}{% include '_includes/body' %}{% endblock %}
{% block foot %}{% include '_includes/foot' %}{% endblock %}

All work great, but did I use it correctly?

The thing that confuses me, is that I didn't have to copy '_layouts' folder with 'base.twig' file to 'de' folder, and modify paths in 'base.twig' for all include filters. Why is it so? Twig renders files of an active locale?

From the localization guide - When Craft is looking for a template, it first sees if a template with that path exists inside a directory named after the current locale, then for the actual path provided.

So in your case, when you're in the de locale, it would look for the following templates:

templates/de/_layouts/base.twig
templates/_layouts/base.twig

and

templates/de/_includes/header.twig
templates/_includes/header.twig

etc, using the first one that exists.

If there's little or no difference between how the site behaves in different locales (other than the translated strings,) then it might not be necessary to override whole templates like that, but it's great when you need it.


How does a CMS work ? How to add articles and manage them? I would like to design a news outlet website, if that's the correct name.

I've drawn a little sketch and I have a pretty good idea about the user interface; things like the site logo, nav-bar, content placement, footer, the easy stuff.

The thing that I don't understand is how does content management work?. I assume that I don't make a webpage.html for each article, right ? And if that's the case, then I am sure that there are other optimized methods of doing this. How will that work ? Let's say that a user clicks on a preview (that's on the first page), where do I send him if I assume that I don't make websites for each article ?

Also, how can I make a top 100 articles based on a marking of my own choosing; example: game reviews with scores from 0 to 100; if a user clicks on Top 100 Games I would like to present him with an ordered list of the top 100 games reviewed by my website.

What about auto-arranging the articles in a chronological order in a specified [div][/div] ? For example: the last five written articles presented chronologically in the middle of the screen from left to right.

I would prefer to design this website using HTML, CSS, JavaScript, PHP, without using platforms like WordPress. This is because I have never used WordPress.

Any advice is welcomed. I have never done such a big project before. I've mainly done simple websites for my job. This is a project form which I hope I can learn lots of new stuff.

Also, please do give me advice if you think that implementing my idea into WordPress is easier than doing it from the ground-up. I mean, I am pretty sure that it's easier, but I haven't used it before and I don't know if I can customize it to my heart's content. I assume that, when using WordPress, you select a "News" Theme that has a built-in CMS for your site which gives you, let's say, a slideshow that arranges the articles in a chronological order. Now, what if I want to change that slideshow into a design of my own ? How do I take take the CMS from point A and implement it over point B ?

Thank you.

Creating a website in Craft CMS as you outline requires a fair bit of knowledge:

HTML
CSS
Tag language, like Twig (which is what Craft CMS uses)
Maybe a little JavaScript
Basics of file management, FTP (or version control)

Wordpress is a tool that may allow you to create your site with less knowledge of the above - there are pros and cons to each approach.

If you have knowledge of the above skills, I suggest watching some basic Craft tutorials, at Mjingo, for example, installing Craft on a local or remote server, and learning the basics. Then you will know if it is the right tool for you.

Here's a big list of Craft resources.


Get relatedTo from Neo field In channel A, we have a Neo field with a couple of different block types, in 1 of those types we have an entries field with channel B entries.

On the channel B entry, I'd like to find out if it is related to a channel A entry through that Neo field.

Going by https://craftcms.com/docs/relations and how it works for a Matrix field I have this:

      {% set partOfChannelA = craft.entries.section('channelA').relatedTo({
        targetElement: entryChannelB,
        field: 'neoField.blockType.fieldHandle'
    }) %}

But that doesn't work :)
Am I missing something or does this simply not work with a Neo field?
Thanks for helping out!

I ended up fixing this with a variable and querying it myself.

In this case I needed the related entry if it was linked and a false if it wasn't.

$neoElement = craft()->db->createCommand()
    ->select('craft_relations.sourceId')
    ->from('relations')
    ->where('craft_relations.fieldId = 110')
    ->andWhere('craft_relations.targetId = :entryId', ['entryId' => $entry->id])
    ->queryColumn();

if(!empty($neoElement)) {
    $parents = craft()->db->createCommand()
        ->select('craft_neoblocks.ownerId')
        ->from('neoblocks')
        ->where('craft_neoblocks.id = :neoElementId', ['neoElementId' => $neoElement[0]])
        ->queryColumn();

    if(!empty($parents)) {
        $entry = craft()->entries->getEntryById($parents[0]);
        return $parent;
    }
}

return false;


Eager Loading a Structure and descendants In looking at the the BaseElementModel:getDescendants() method and saw it checks for eager loading elements named 'descendants.'

// Eager-loaded?
if ($this->hasEagerLoadedElements('descendants'))
{
    return $this->getEagerLoadedElements('descendants');
}

I added with and the descendants condition to a Structure and the page is now loading with a few less queries.

{% set entries = craft.entries({
    section: 'sectionHandle',
    limit: null,
    with: [
        'descendants'
    ]
}) %}

Can anybody explain what is happening here?

Craft 2.6.2789 added this feature, which is seems you've reverse engineered. :)

  It is now possible to eager-load Structure entries' and categories' descendants using the 'descendants' handle.


Save user group event in Control panel I have a plugin that saves users into a registration group like:

 if (craft()->request->isSiteRequest()) {
  //etc
  $groupId = '1';
  craft()->userGroups->assignUserToGroups($user->id, $groupId);
}

However if i listen for the user save event for the control panel:

if (craft()->request->isCpRequest()) {
  //etc
  $groupId = '1';
  craft()->userGroups->assignUserToGroups($user->id, $groupId);
}

This doesnt work. I also tried passing an array as groupId(s) but the group permission never gets ticked.

Is there another way of assigning a new user saved in the back end to a specific permission group?

It happens here (maybe intended, maybe a bug):

https://github.com/craftcms/cms/tree/master-v2/src/controllers/UsersController.php#L1757

For news users $groupIds is an empty string, which means the expression ($groupIds !== null) becomes true. At line 1780 $groupIds get passed to userGroups->assignUserToGroups() ... inside this method the $groupIds variable is casted to an array.

Eventually this overwrites the groups you've set by your onSaveUser event.

Here is a (dirty) hack that works

craft()->users->onSaveUser = function ($event) {

   craft()->userGroups->assignUserToGroups($user->id, $groupId);
   craft()->params['noGroupReset'] = true;

};

craft()->userGroups->onBeforeAssignUserToGroups = function ($event) {

   $noGroupReset = (isset(craft()->params['noGroupReset']) && craft()->params['noGroupReset'] === true);

   if (count($event->params['groupIds']) == 0 && $noGroupReset) {
      $event->performAction = false;
   }

};


Craft and Plugins are licensed, but I'm still seeing warnings on Production In my production environment, I have administrative changes disabled, so I see the following messages:
* You’re running Craft Pro with a Craft Solo license. Please fix on an environment where administrative changes are allowed.
* 3 plugins have licensing issues. Please fix on an environment where administrative changes are allowed.

Fair enough. I logged in to my local environment, and licensed the CMS as well as the plugins. This triggered a change to project.yaml and I can see the addition of the licenses. I then pulled to my production environment, synced changes, and I expected to see these warnings disappear. However, the warnings are still there.
Any suggestions as to what I'm doing wrong here?
====
UPDATE
Brad's answer below resolves the issue, but there's one additional note. There are many caches in the CMS > Utilities > Clear Caches. The cache that stores licensing is "Data caches".

You probably just need to clear the Craft storage/cache folder on production.
Licensing info is cached for 24 hours at a time.


Installing Craft CMS on Linux Mint OS? I am totally newbie in Craft CMS so don't be harsh to me.

While coming to my problem I am getting Error : 404 while installing Craft CMS on my local server Linux Mint OS please someone guide me to install Craft CMS successfully on my local server,I followed below basic steps..

Created db gave db details in db.php.
Renamed htaccess to .htaccess.

My folder structure was

/var/www/html/Craftdemo/craft and public

  My local server configured correctly and is working good enough to run
  my other sites like Wordpress/Magento and some JS files.

Thanks in advance

Nobody is going to be harsh here, so don't worry. The Craft community is a nice place :-)

Sounds like the site root is not pointing to the Craft public accessible folder (the one with index.php). Can you open the URL to another file in the site root? Add a test.txt file for example and try to open it in your browser.

Regarding the .htaccess file: You are using apache, right? .htaccess doesn't work for nginx. Might sound obvious, but you wouldn't be the first to make this mistake. ;-)


Is using craft.config to access siteUrl possible? In the past I would comment out analytics code on my dev and staging sites then uncomment the code when it went live. I ran across this page in the Craft docs the other day and started thinking, can I use this to access the siteUrl from the environment variable array and specify a value in my conditional (i.e. {% craft.config.environmentVariable('siteUrl', 'http://www.example.com') %}? This way I can add the analytics code and only worry about it loading on the live site.

Yes, if you set up proper multi environment configs, this isn't very hard. My config/general.php file usually look something like this:

return array(

  '*' => array(
     // some general settings here
  ),

  'mydomain.craft.dev' => array(
    'environment' => 'local',
    'devMode' => true,
    'useCompressedJs' => false,
    'siteUrl' => 'http://mydomain.craft.dev/',

    'environmentVariables' => array(
      'fileSystemPath' => $_SERVER['DOCUMENT_ROOT'] . '/../',
      'publicRootPath'    => 'public/'
    ),
  ),

  // staging and other environments here

  'mydomain.com' => array(
    'environment' => 'prod',
    'devMode' => false,
    'useCompressedJs' => true,
    'siteUrl' => 'http://mydomain.com/',

    'environmentVariables' => array(
      'fileSystemPath' => '/path/to/system/root/',
      'publicRootPath' => 'html/'
    )
  )

);

Then, to only include the GA tracking tag when I'm on the prod server, I include this in my html head:

{% if craft.config.environment=='prod'  %}
  <script>
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

    ga('create', 'UA-XXXXXXXX-X', 'auto');
    ga('send', 'pageview');
  </script>
{% endif %}

You could of course check siteUrl instead, but I prefer to use something a little more abstract. Just in case the siteUrl changes.


Using Categories with Structures? I have two structures: Focus Areas & Initiatives.

I'd like to be able to associate the two of these structures. Here's a potential example:

Focus Areas:

Sports
Music
Art

Initiatives:

Basketball
Soccer
Trumpet
Painting

My organization has a number of Initiatives, each fit under a certain Focus Area.

On each Focus Area page, I would like to show all Initiatives associated. Currently, for each Initiative, I have a Radio Button for each Focus Area it fits under, but am having trouble thinking of how to further narrow down entries to show from the example below (which shows all initiatives):

{% set entries = craft.entries.section('initiatives') %}
{% for entry in entries %}
    {{entry.title}}
{% endfor %}

Would this be an appropriate use case for Categories? Should I instead be using Entry Types for each Focus area?

There are a number of ways to organize this using any combination of channels, structures, or categories — it's hard to give a recommendation on which way is better without knowing a little more about your site requirements.

Much will depend on things like:

Will there be pages for both 'focus-areas' and 'initiatives' (or is one just used for organization)?
How the uri's should look? (i.e. 'focus-area/initiative/' or '/focus-areas/focus-area/' & '/initiatives/initiative')
Are the relationships 'one-to-one' or 'many-to-one'?
Are the pages hierarchical and/or need a specific order defined?
Do the pages need entryTypes (because the layout and/or field requirements are unique for different pages)?
Do you need to generate site-navigation dynamically?

Answering these questions will generally narrow down the options.

  On each Focus Area page, I would like to show all Initiatives associated. Currently, for each Initiative, I have a Radio Button for each Focus Area it fits under.

Typically, instead of a radioButton, you would create a relationship between any two channels/structures/categories using the EntriesFieldType. Once you have added the field to your focus-areas field layout, and added some related initiative entries, you can access the related initiatives using:

{% for initiative in entry.initiatives %}

{{ initiative.title }}

{% endfor %}

or

{% set initiatives = craft.entries.section('initiatives').relatedTo(entry) %}
{% for initiative in initiatives %}

{{ initiative.title }}

{% endfor %}

  Would this be an appropriate use case for Categories?

Maybe. If you want to conceptually consider them as categories (and categories fit all your other needs) then go for it. Otherwise the difference between categories and structures/channels is pretty minor (with the exception that categories do not support entryTypes).

  Should I instead be using Entry Types for each Focus area?

Maybe. EntryTypes are generally used when the field and/or layout requirements are unique in some way for the various entries. If the relationship between 'focus-areas' and 'initiatives' is one-to-one, and if you want the uri's to be 'focus-area/initiative' then a good option might be to combine the two structures together hierarchically and use EntryTypes to define the unique layout and fields requirements for each. In your template you would then check the entry's type and change the layout or include a sub-template.

{% if entry.type = "initiative" %}
    {% include '_initiative.html' %}
{% endif %}

You can also use this approach site-wide to generate more dynamic site navigation, using craft's nav tag.


Send freeform email notification to manually entered recipient address I'm trying to build a "send this page to a friend" form in Freeform. My code looks like this:

{% set form = craft.freeform.form("emailToAFriend") %}

{{ form.renderTag({returnUrl: "contact/success"}) }}

    {% if form.hasErrors %}

            {{ "There was an error submitting this form"|t }}

    {% endif %}

    {% set recipientsName = form.get("recipientsName") %}
    {% set recipientsEmail = form.get("recipientsEmail") %}
    {% set yourName = form.get("yourName") %}
    {% set yourEmail = form.get("yourEmail") %}
    {% set sharedUrl = form.get("sharedUrl") %}
    {% set message = form.get("message") %}

    {{ yourName.label }}
    <input name="{{ yourName.handle }}" value="{{ yourName.value }}" />
    {{ yourName.renderErrors() }}

    Your Email Address
    <input name="yourEmail" />
    {{ form.get("yourEmail").renderErrors() }}

    {{ recipientsName.label }}
    <input name="{{ recipientsName.handle }}" value="{{ recipientsName.value }}" />
    {{ recipientsName.renderErrors() }}

    Their Email Address
    <input name="recipientsEmail" />
    {{ form.get("recipientsEmail").renderErrors() }}

    {{ message.renderLabel() }}
    {{ message.renderInput() }}
    {{ message.renderErrors() }}

    <button type="submit">Submit</button>

{{ form.renderClosingTag }}

How could I get the field in recipientsEmail to pass to that recipient and choose the template?

The recipientsEmail field should be an Email fieldtype, and in Composer you need to set the notification template in the Field Property Editor column (on right) for that field and it'll send an email to the email that is entered in that field when the form is submitted. :)

View the documentation page here for more information about email notification options:
https://solspace.com/craft/freeform/docs/email-notifications/


Craft creating dirty transparent background on image transformations / resizing for anyone experiencing dirty transparent backgrounds when you transform transparent PNG images with Craft like this:

Source Image:

Resized, dirty:

Craft Command: craft.assets.id(2).first().getUrl({width: 300})

If you don't see the dirt, watch screen from the side!

The reason is the GD image library. If you switch to imagick, the transparent background will be clean:

Resized, clean:


Bootstrapping Craft for PHPUnit on command line I'm trying to run some commands on a Jenkins server to have PHPUnit execute the tests and report the results.

When I do require_once 'craft/app/bootstrap.php'; It is giving an error saying: PHP Notice:  Undefined index: SERVER_NAME in craft/app/bootstrap.php on line 105

I read that you cannot use bootstrap.php in the craft/app folder because you're essentially trying to bootstrap a webapp (and this server isn't a webserver). It was suggested that I use craft/etc/console/yiic.php as my bootstrap file for PHPUnit. However, this is throwing errors about CDbConnection and is unable to connect.

Is there any way to bootstrap Craft from a command line to run PHPUnit? I'm unable to get it working without an apache server.

I read that you cannot use bootstrap.php in the craft/app folder because you're essentially trying to bootstrap a webapp (and this server isn't a webserver).

Not sure where you read that, but that doesn't sound right.

I'm assuming you've got a multi-environment config setup?  If so, then manually set the CRAFT_ENVIRONMENT PHP constant before you load the Craft bootstrap.php file to the environment you want Craft to load in the config files.

That will get rid of the Undefined index: SERVER_NAME error you're getting as well as should fixed your database connection issue.


How to set up multi-env in Craft 3 with .env files? How do I take advantage of the new .env files? I want to setup a local and production environment in Craft 3.

Anyone know how to do this or know of any docs out there explaining it ?

These are the two approaches I usually choose from:

Option 1: the 'default' Craft 3 way

Create a .env file for every environment you create, and add it to your .gitignore file (if it's not yet in it). In this file, you put all environment-specific details;
Craft, by default, will recognize and use those details.
In your Craft config files, you can use the ENVIRONMENT as defined in your .env file to adjust the settings for one specific environment. So, the config that applies all the time is set in an array with the key '*', and the config that's specifically for the dev environment, is in the array that has the 'dev' key (If you use the default general config file)

Option 2: the .env.php way

One of the reasons this approach exists, is that the makers of PHP dotenv (used in option 1) 'warn against using it in production' (as quoted from the README of option 2). The method as linked in the title uses a PHP file and some minor alterations to your config and index files to let you maintain a multi environment build.


How to build contact form from scratch (no plugin) I want to build a simple contact form without plugin, i am new to craft cms coming from wordpress, how can i build a simple form that will be save on entries and will send an email.

Here’s an example of how you can do exactly that using only the CraftQL plugin: Using Vue.js + GraphQL to make Practical Magic

You can also do it with a frontend Entry form without any any plugins at all, and without JavaScript or GraphQL: Craft CMS Entry Form Example

And in general can do a whole lot without plugins: Cutting was he Cord: Removing Craft CMS 3 Plugins


Use Dukt Videos with HTTPS This is a specific question about the Dukt videos plugin. I have a site that's all HTTPS and I can't seem to find a way to switch all the embeds to also use HTTPS?  Is there an option anyone else knows of?

Sorry about that guys, this issue has been fixed in Videos 1.0.20:

https://dukt.net/craft/videos/updates#v1.0.20


grab 'environmentVariables' with a tag 'dev' => array(
        'siteUrl' => array(
            'de_ch' => 'http://blabla.dev/',
            'en' => 'http://blabla.dev/en/',
        ),
        'environmentVariables' => array(
            'basePath' => 'path',
            'baseUrl' => 'http://url-without-locale-segment.dev/',
        )
    ),

I set a baseUrl inside environmentVariables to be able to grab the url without a locale. But when I enter {{ baseUrl }} in the template it returns an error:

  Variable "baseUrl" does not exist

How do I have to write this?

You can get to any of your config variables (including custom ones) like this:

{{ craft.config.xyz }}

The environmentVariables array is no different:

{{ craft.config.environmentVariables.baseUrl }}

See the craft.config documentation.


project.yaml stopped syncing changes in the staging process I'am a bit helpless at the moment, because my project staging workflow using project.yaml stopped working and a) I don't know why and b) have no clue if I can solve it.

Problem:
Until some days ago my staging worked like that:

1.) We are 3 developers working in our office, sharing the craft db on a central mysql. Dev User files were synced using an internal dropbox. When we wanted to bring our Craft DB changes to the QS machine, we enabled projectConfig, craft wrote a project.yaml, we pushed it to our repo and the QS installation of Craft took the project yaml and imported them. This worked great.

2.) Now this stopped working. We had a couple of new globals, fields, etc.  but they were not taken over to QS

3.) When I look into my database I can see the fields, globals etc. in the corresponding tables (looking good). But when I look at the config column in the info table, the settings there do not match my database. e.g. I found the same fields and fieldgroups with different UIDs duplicated in there. So I know there is something wrong here, but I do not know what. And I also know that my project.yaml is the same as my config column so maybe this is the reason, why my QS installation does not take over any recent changes to my project db structure.

So my questions are rather general:
- Can this problem be solved?
- Can the config column in the info be rewritten according to the real existing structure on the source Craft installation?
- Can a broken Craft database in some way be repaired?

My problem is that we already have some (not too much tough) customer content in the QS system and unless I want to manually recreate the Craft installation I would definitely prefer a way of repairing it.

Thanks,
Matthias

P&T recently released an update with a new console command:

project-config/rebuild

This does exactly what it sounds like, it rebuilds the config ...


On the P&T form add-on you have to use a message field is there a way round this? Unless I am misunderstanding the docs for the P&T form, it says you have to include the message field, if some forms don't have a message field is the only way to not show this hide it with CSS?

Just wondered what other people are doing for forms - I am also looking at the Sprout form add-ons.

Why not just add a hidden input called "messages" set to "" (or if that doesn't work ".")?

What's the use case for wanted to send a contact email with a message body?


Sometimes getting sent to /admin/undefined after login After logging in to the Craft admin area I sometimes(!) get routed to /admin/undefined instead of /admin/dashboard.

Anyone knows were to start looking to solve this issue?

This happened for me when I had the LastPass browser plugin version 3.3.1. Once I upgraded to 4.1.29, the issue went away.


Impersonating a User from a plugin, with specific page redirect Part of a plugin I am writing needs to handle impersonating a user, in the same way that Craft offers the built in "Log in as X" for admins in the back end.

I have that working by essentially copying the /app/controllers/UsersController actionImpersonate() function into my plugin.

However, when the action is run, the newly logged in user is always being redirected to the homepage - which makes sense as it's the default page that front-end logins go to. But, I want to override it. I want my plugin to take them to a page I dynamically set. I can't seem to get it to happen. Here's my code:

public function actionMyAction()
{

    // basic security precautions
    $this->requirePostRequest();
    $this->requireAdmin();

    ... some stuff not relevant to the question ...

    // get the user we want to impersonate
    $originalUserId = craft()->userSession->getId();
    $orderOwnerId = $order->customer->user->id;

    // impersonate the user
    craft()->httpSession->add(UserSessionService::USER_IMPERSONATE_KEY, $originalUserId);

    if (craft()->userSession->loginByUserId($orderOwnerId))
    {
        craft()->userSession->setNotice(Craft::t('Logged in.'));
        // $this->_handleSuccessfulLogin(true);
        $this->redirectToPostedUrl();
    }
    else
    {
        craft()->httpSession->remove(UserSessionService::USER_IMPERSONATE_KEY);
        craft()->userSession->setError(Craft::t('There was a problem impersonating this user.'));
        Craft::log(craft()->userSession->getUser()->username.' tried to impersonate userId: '.$userId.' but something went wrong.', LogLevel::Error);
        }
    }
}

I'm expecting that to redirect the newly logged in user to the page that the form was posted from - but it doesn't. Also, and I don't know if it's related, if I uncomment the $this->_handleSuccessfulLogin(true); line I get an error. That line is not commented out in the original function, and looking at the Craft docs to try and learn what it does, it says the function is deprecated ( https://craftcms.com/classreference/services/UsersService#handleSuccessfulLogin-detail )

Since this is an action in your own plugin's controller, you can literally do anything you want after the login happens.

if (craft()->userSession->loginByUserId($orderOwnerId))
{
    $this->redirect('https://www.reddit.com/');
}

  if I uncomment the $this->_handleSuccessfulLogin(true); line I get an error.

Because that's a private method you probably didn't copy over from Craft's UsersController.php.  You don't have to use it if you don't want to.

  it says the function is deprecated (https://craftcms.com/classreference/services/UsersService#handleSuccessfulLogin-detail)

Same method name (mostly), but not in the UsersController... it's on the UsersService.  It's also public, not private.


Include Craft JS object In the controller documentation for plugins, there's a section that talks about routing to specific actions using a Craft object like this:

var url = Craft.getActionUrl('cocktailRecipes/ingredients/saveIngredient', { id: 10 });

I think this object is the one in /craft/app/resources/js/craft.js, but I can't figure out how to make it available. I tried including it via includeJsResource, but this doesn't appear to be working

{% includeJsResource "resources/js/craft.js" %}

What do I need to include to be able to use this object in my JavaScript (it is not a load ordering issue, the URL generated by includeJsResource goes to the 404 page)?

The Craft global variable is available to any Javascript running in the backend/Control Panel, without including anything.

It's not possible to include, reference or use the global for any code running in the frontend.

EDIT:

To provide access to a controller action for frontend Javascript, I'd recommend setting up a site route in your plugin's main class. The following will route the URL http://yourbaseurl/myplugin/foobar/add to ExampleController:

public function registerSiteRoutes()
{
    return array(
        'myplugin/foobar/add' => array('action' => 'myPlugin/example/add'),
    );
}

As for the ExampleController, be sure to set the $allowAnonymous class variable to true. This allows visitors that aren't logged in to Craft access (beware that this will make all your controller´s actions accessible without login):

class MyPlugin_ExampleController extends BaseController
{
   protected $allowAnonymous = true;
   public function actionAdd()
   {
       // Your code here
   }
}


Basics of overriding an admin page template - Craft 3 I want to override the admin/users page template when a plug in is installed.

Detail:
On the user page domain.com/admin/user all the groups are listed in the sidebar area. I get this from the \vender\craftcms\cms\src\templates_layouts\cp.html file. I want to install/use use a custom template for the user page using a plug in.

What are the basics of overriding a admin template through a plugin?

Edit - More detail:

I have a plugin that creates a new controller exactly the way that is proposed in this post. The controller does two things (maybe more later):

1) On entries page it displays all the entries to a logged in user that was posted by them and others from their same group. It does not display entries that were posted by users in other groups.

2) On user page it displays only users from their own group. It does not display any other users from other groups.

On the users page all the groups are listed here:

It does not make sense to display all the groups here as the logged in user can only see or edit users in their own group.

I need to change what is displayed in the group listing area.

There are multiple ways to achieve your goal, I think the most elegant one is to overwrite the default route /users with your custom one and replace the elementType

Things you need to do

Change the default route to your template
Copy the default template and change it's element type
Create a custom element type that extends craft/elements/User

You can change the route of all navigation  bar items (modifyCpNav)

Event::on(
    Cp::class,
    Cp::EVENT_REGISTER_CP_NAV_ITEMS,
    function(RegisterCpNavItemsEvent $event){
        // the 4th element is the "User", you can change the URL to your
        // custom template instead of the default template
        // I suggest you to loop all `navItems` and find
        // the correct user instead of assuming it's the 4th
        // Craft::dd($event->navItems);
        $event->navItems[4]['url'] = 'path/to/template/user';
});

Then just copy the Craft templates/user/index template in your plugin to create an index page

{% if CraftEdition != CraftPro %}
    {% exit 404 %}
{% endif %}

{% requirePermission 'editUsers' %}

{% extends "_layouts/elementindex" %}
{% set title = "Users"|t('app') %}
// changes start
// replace the elementType with your custom element type
{% set elementType = 'prefix\\namespace\\elements\\User' %}
// changes end
{% block actionButton %}
    {% if currentUser.can('registerUsers') %}
        {{ "New user"|t('app') }}
    {% endif %}
{% endblock %}

Then in your src/elements folder create a new User class to overwrite the sources

class User extends \craft\elements\User{ //<-- extend the default User element

    /**
     * @inheritdoc
     */
    protected static function defineSources(string $context = null): array
    {
        $sources = [
            [
                'key' => '*',
                'label' => Craft::t('app', 'All users'),
                'criteria' => ['status' => null],
                'hasThumbs' => true
            ]
        ];

        // Overwrite the sources / usergroups...
        // usually Craft will search for usergroups at this place..
        // just leave it empty, so you'll only see the "default" group

        return $sources;
    }
}

Don't forget to register your element

TL/DR
You could as well just hide the other sources via CSS/Javascript - but I would not suggest it, since everyone is able to see the other groups with minor Javascript skills


Using Craft::import() to include external resource into the Craft Namespace Looking at this answer, I suppose I am under the assumption that Craft::import() will take an alias, find the path, and import that class into the Craft namespace... which would be the benefit over simply using require_once().

Currently I import with:
Craft::import('plugins.myplugin.resources.chargebee.lib.ChargeBee', true);

Which works, however to use ChargeBee.php, I have to reference it from the global namespace. Not sure if this is the expected behaviour, but I would love to work within the Craft namespace if possible. Any help is greatly appreciated!

and import that class into the Craft namespace

Nope... it'll import that file, but will use whatever namespace the file is using (including global).

My guess is that the ChargeBee.php file has a ChargeBee class in it that lives in the global namespace, which is why you have to reference it there.


How can I set a Neo field's values from my plugin/module? I wish to programmatically set the value of a Neo field.
This is my current approach:

$entryData = self::setupEntryData($item);
$entry = new Entry($entryData);

$fieldValues = [
    'heading' => $entryData['title'],
    'blocks' => [
        'blocks' => [
            'new0' => [
                'modified' => 1,
                'type' => 'wysiwyg',
                'enabled' => 1,
                'collapsed' => 0,
                'level' => 0,
                'fields' => [
                    'grayBackground' => true,
                    'wysiwyg' => '
test
',
                    'buttons' => null,
                ]
            ]
        ]
    ],
];

$entry->setFieldValues($fieldValues);

Of course this doesn't work.
Can someone point me in the right direction?
Here is a screenshot of the Form Data that is passed when setting the value manually from Craft CMS.

Just to confirm, my Neo field is called blocks.
My target blog type has a handle of wysiwyg.
The Redactor field I target has a handle of wysiwyg.

Thank you!

I just figured it out.

For anyone facing the same issue, here is what worked for me:

$entryData = self::setupEntryData($item);
$entry = new Entry($entryData);

$fieldValues = [
    'blocks' => [ // Neo field handle
        'new0' => [
            'modified' => 1,
            'type' => 'wysiwyg', // Neo block handle
            'enabled' => 1,
            'collapsed' => 0,
            'level' => 0,
            'fields' => [
                'grayBackground' => true, // Neo block field
                'wysiwyg' => '
test
', // Neo block field
                'buttons' => null, // Neo block field
            ]
        ]
    ],
];

$entry->setFieldValues($fieldValues);


How do I save a Plugin's date settings-field? I've got a plugin with some custom settings, like this:

protected function defineSettings()
{
    return array(
                 'serviceendpoint' => array(AttributeType::String, 'required'=>true),
                 'passkey' => array(AttributeType::String, 'required'=>true),
                 'newregistrationdate' => array(AttributeType::DateTime, 'required'=>false),
                 );
}

Then I have a _settings template, which renders the form:

{{ forms.textField({
    first:        true,
    label:        "CRM Endpoint URL"|t,
    id:           'serviceendpoint',
    name:         'serviceendpoint',
    instructions: "The URL for the CRM service ."|t,
    value:        settings.serviceendpoint,
    autofocus:    true,
    placeholder: "https://example.com/api/...",
    errors:       settings.getErrors('serviceendpoint')
}) }}

{{ forms.textField({
    label:        "The service passkey"|t,
    id:           'passkey',
    name:         'passkey',
    instructions: ""|t,
    value:        settings.passkey,
    placeholder: "1234...",
    errors:       settings.getErrors('passkey')
}) }}

Val: "{{ dump(settings.newregistrationdate) }}"

{{ forms.dateField({
    label:        "New registrations after this date"|t,
    id:           'newregistrationdate',
    name:         'newregistrationdate',
    instructions: "Users registered after this date will get a welcome email"|t,
    value:        settings.newregistrationdate.date|default,
    errors:       settings.getErrors('newregistrationdate')
}) }}

The String-typed values are saved just fine. But the DateTime always comes back as false.

I've tried adding a prepSettings function, and doing:

 $settings['newregistrationdate'] = new DateTime($settings['newregistrationdate']['date']);

but it makes no difference.

What does prepSettings have to return for DateTime typed fields?

Yup, you need to use AttributeType::Mixed as Justin Kimbrell suggests. The date will then be escaped and stored in the database like this: *

{"newregistrationdate":{"date":"2\/1\/2015"}}

Now, the dateField in your settings template will expect a DateTime object for its value – so just passing getSettings() as is will make it choke. You can get around that by adding the following to the getSettingsHtml() method:

$settings = $this->getSettings();
if ( isset( $settings[ 'newregistrationdate' ][ 'date' ] ) ) {
    $settings[ 'newregistrationdate' ] = new DateTime( $settings[ 'newregistrationdate' ][ 'date' ] );
}
return craft()->templates->render( 'yourPluginHandle/settings', array(
    'settings' => $settings,
) );

...and then finally, make sure the dateField constructor looks in the right place for its value by removing the date key of the settings.newregistrationdate property:

{{ forms.dateField({
    label:        "New registrations after this date"|t,
    id:           'newregistrationdate',
    name:         'newregistrationdate',
    instructions: "Users registered after this date will get a welcome email"|t,
    value:        settings.newregistrationdate,
    errors:       settings.getErrors('newregistrationdate')
 }) }}

Solution is tested.

Note that the date object is actually serialized, escaped and stored properly even if you use AttributeType::DateTime, however getSettings() will always return the attribute value as false. Could be a bug?


Craft Installation Next Button Not doing anything I am in the first step of the installation. I entered my email, username and password and clicked on the next button, but it is not doing anything.

It makes a post request to:
/var/www/html/test_craft/craft/app/index.php

And a Get request to:
http://localhost/public/index.php?p=admin/resources/images/spinner_submit.gif&d=1465331044

Looks like the get request is not returning anything because in firebug, the response is a spinning wheel.

Well, things should be going very smoothly from here, so there is pretty surely something not right with your installation.

1) did you make sure to rename the installed file public/htaccess to public/.htaccess? I'm not sure if this is critical to the installer, but it might be.

2) You can look in craft/storage/runtime/logs. There you find craft.log and phperrors.log. Either may hold information to help.

3) It sounds that your database login config is ok, as otherwise the Craft installer would notify about that, but you may not have all the other server requirements in place yet. See: https://craftcms.com/docs/requirements.

For requirements testing, see: Is there a quick way to check a server for Craft's minimum requirements?

4) Getting no response would be quite unusual. It's possible that your Craft installation is faulty -- FTP in general is often not entirely reliable. You could remove, then re-upload and replace the installation. If you do this and can, I'd suggest uploading the zip, then unzipping it on the server. Again, then, don't forget to rename the htaccess to .htaccess.

5) all this presumes you are running on Apache. If Nginx instead, here are two references that should help. I'd go with the first as that's from the Craft team based on what works for others. I use Nginx all the time, as do many others, and it's fine once configured:

What is the recommended Nginx configuration for Craft?

https://gist.github.com/kenzie/5811327

Good fortune then. Again, Craft installs are nearly as effortless as Craft updates, unless there is something wrong in the configuration or preparations.


Multisort with supersort plugin I have entries that I would like to sort by 2 fields. First I would like to sort (or group) all of the entries in alphabetical order by a category field (brand), and then within each grouped brand I would like to sort the entries by a number field ascending (size).

I can perform both sorts individually with the syntax below, but I’m having difficulty combining them for a multisort-like function.

 entries|supersort('sortAs', '{ brand.first.title }')
 entries|supersort('sortAs', '{ size }', SORT_NUMERIC)

Try to group the entries sorted by size using the group filter:

{% set entriesSorted = entries|supersort('sortAs', '{ size }', SORT_NUMERIC) %}
{% set entriesByBrand = entriesSorted|group('brand.first.title') %}
{% set entriesByBrand = entriesByBrand|supersort('ksort') %}

{% for brand, entriesInBrand in entriesByBrand %}
    {% for entry in entriesInBrand %}
        <li>{{ entry.title }}</li>
    {% endfor %}
{% endfor %}


Get a key value from a JSON asset in PHP I'm using the Apple News plugin to try and display a tweet that's been added as a JSON asset in a matrix field. The JSON looks something like this
{
    "title": "https://twitter.com/TehseenLadha/status/1291773476877959169",
    "description": null,
    "url": "https://twitter.com/TehseenLadha/status/1291773476877959169",
    ...
}

According to the Apple News Publisher docs, all you need is the tweet's URL. I'm trying to get it by converting the JSON file to a string with file_get_contents and then using json_decode, but it's not working. This is what I have in MyNewsArticle.php:
case 'tweet':
  $asset = $block->tweet->one()->getUrl();
  $string = file_get_contents($asset);
  $jsonArr = json_decode($string, true);
  $tweetUrl = $jsonArr['url'];

  if ($tweetUrl) {
    $components[] = [
      'role' => 'tweet',
      'layout' => 'tweetLayout',
      'URL' => $tweetUrl,
    ];
  }
break;

It's grabbing the correct URL of the asset, but fails with failed to open stream: Operation timed out on the $string = file_get_contents($asset); line. Apparently this is something to do with IPv4 vs IPv6? I'm not certain how to get around it though.

I assume that $block->tweet->one() returns an Asset element in your matrix block called tweet. I suggest that you use the getContents() method on Craft's Asset element type to retrieve the string content of the actual file. Your code block would look something like this:
case 'tweet':
  $tweetFileContent = $block->tweet->one()->getContents();
  $tweetJson = json_decode($tweetFileContent, true);
  $tweetUrl = $tweetJson['url'];

  if ($tweetUrl) {
    $components[] = [
      'role' => 'tweet',
      'layout' => 'tweetLayout',
      'URL' => $tweetUrl,
    ];
  }
break;

However, I would recommend extending your code as follows to address empty state and potential exception:
case 'tweet':
  if (empty($block->tweet)) {
    // return early or do something else
  }
  try {
    $tweetFileContent = $block->tweet->one()->getContents();
    $tweetJson = json_decode($tweetFileContent, true);
    $tweetUrl = $tweetJson['url'];

    if ($tweetUrl) {
      $components[] = [
        'role' => 'tweet',
        'layout' => 'tweetLayout',
        'URL' => $tweetUrl,
      ];
    }
  } catch ($e) {
    // getContents() throws
    // InvalidConfigException if [[volumeId]] is missing or invalid,
    // AssetException if a stream could not be created
  }
break;


Update from 3.3.4.1 to 3.6.11.2 advice What is the best way to do this?
I also have a number of plugins that all need updating from the same time period.
I don't think any of the breaking changes affect anything I've done, but I wonder/expect that some plugins may need to be updated to work with the new craft versions.
The PHP requirements changed twice during the various updates.
I'm currently running PHP 7.2 but I know that Craft 3.6 needs 7.2.5 or later.
I can make 7.4 available but do I change it before I start the updates or after.
I have already tried doing this once from the control panel, and Craft seemed to update and the control panel was available but all the plugins were disabled and when I tried to update any plugin it failed and I got an Internal server error page. The composer.json file hadn't been updated to show the new version of craft, I tried editing it and changing the PHP version in the config.platform but still couldn't update any plugin.
I can ssh into the server but my command line knowledge is very limited and potentially dangerous.
My server is already running composer 2.0.6

This is how I would go about this (in a local or dev environment):
PHP
First, activate PHP 7.4 and check if the site still works as it should (frontend, backend). I don't know exactly if version 3.3.4.1 works with PHP 7.4, but it's easier to switch back to an older PHP-version than reverting a Craft upgrade.
Craft
After you've made sure that the site still works, you can start the upgrade to Craft 3.6.11.2. I would kindly but strongly suggest that you use Craft's command line commands for this. In our experience, this gives you more detailed error messages.

First, make a backup of both your files and database (create a server snapshot, or manually create a backup)
Now, open a terminal. Don't be scared, you'll love it. Or not, depending on the outcome of this experiment.
Navigate to your project's root folder.
Run ./craft update <-- This will run the craft script in the current folder (./) and then it tells Craft to run the update command. This command will only show you what needs to be updated, it will not update anything.
Now, you should see a list of updates of both Craft and plugins. I'd start by updating Craft itself. Baby steps, you know?
Run ./craft update craft <-- This tells Craft to update ... itself. In the background, composer.json will be changed and Composer will update Craft. If that fails, Craft will tell you why. If something goes wrong, Craft will ask you if you want the changes to composer.json reverted. If you choose to do this, you can then fix the problem and run the update again. If you don't revert the changes, you can fix the problem and run composer update. If you update Craft using Composer, you'd still have to run ./craft migrate/all to run any database migrations that come with newer versions.
If the update succeeds, you can then ./craft update all, to update all plugins. This, again, changes your composer.json file and runs Composer in the background.

Common pitfalls
File or folder permissions
Your vendor folder, your config/project folder ... Craft needs permission to change things in order to proceed with the update. Check your permissions and try again.
Composer mismatches
A failing update could be Composer throwing an error. For instance, if your composer.json file explicitly says "Use PHP 7.0", and Craft 3.6 requires PHP 7.2, you'd get an error. In this case, alter composer.json and try again.
Luck and common sense
Most of the times, Craft updates just work. If they don't, put on your smart hat and try to read the errors that Craft or Composer throws at you. Another great place to look for errors is Craft's log (storage/logs/web.log). It's much easier to come up with a solution if you know what the problem is. Good luck, and remember ... backup first!


How to deploy website from dev to staging from localhost to remote server using composer I want to upload all my Craft files along with the database to an Ubuntu server using composer. This server is an EC2 instance of AWS.

Thanks for the help!

There is a course on CraftQuest regarding deployment of Craft CMS you might want to check out: https://craftquest.io/courses/deploying-craft-cms-3

For my personal workflow, I develop locally then push my codebase to Github. Since my servers are built using Laravel Forge, I have it set up to deploy my code to my server, which can be an AWS server, Digital Ocean, or any number of places.

For some sites, I use a more robust deployment service. I've used both Envoyer.io and Deploybot to do that. I wrote a post on the Deploybot set up I used. You can find that post here: https://supergeekery.com/blog/laravel-forge-and-deploy-bot


Pagination and Entry Model on Homepage On my site I have some entries with images. In the entry template I paginate the images like so:

{% paginate entry.images.limit(1) as images %}

My homepage is a single random entry and I want to paginate it as well. The Problem is, paginate expects an elementcriteriamodel, not an array. So this doesn't work:

{%
set project = craft.entries()
    .section('projects')
    .orderBy('RAND()')
    .with([
        ['images', { withTransforms: 'width' }],
        ['category']
    ])
    .one() %}
{% paginate project.images.limit(1) as images %}

I tried this, but that somehow doesn't work in Craft 3.

{% set queryParams = {
    with:[['images', { withTransforms: 'width' }],['category']]
}
%}

{%
set project = craft.entries(queryParams)
    .section('projects')
    .orderBy('RAND()')
    .one() %}

{% paginate project.images.limit(1) as images %}

Any solutions?

project.images is an array because you are eager-loading the images.

Since you’re only loading one project entry, you’re not actually gaining anything by eager-loading the images (or category), though. In fact, you’re actually slowing things down a bit. Eager-loading does come with a little bit of overhead, so you should only use it when you’ve got an “n+1” problem, as described on the Eager-Loading Entries page.

So to get this working, just remove the with param.

{% set project = craft.entries()
    .section('projects')
    .orderBy('RAND()')
    .one() %}

{% paginate project.images.limit(1) as images %}

Note that this will also affect how you access your category, as project.category will go from an eager-loaded array, back to a category query.


Auto login after password reset? I like the setting autoLoginAfterAccountActivation. Is there something similar to log in users after a password reset?

I can approximate this by using the users.onSetPassword event, confirming the user isn't already logged in (i.e. using a normal set password form), and confirming that the user model doesn't have an unverifiedEmail value (i.e. is a brand new user), and then using craft->userSession->loginByUserId() but this seems like a very roundabout and potentially stupid way to do this.

Currently nothing native like that. The full list of Craft config settings can be found here.

You might want to consider adding this as a feature request, though!


Link to a front-end upload in email notification using the Sprout Forms plugin I'm trying to add a link to a front-end upload in an email notification.  The docs say "To send notifications that include a direct link to your file, you can enable Template Overrides". I've done that, but all I can get is a link to a temporary file in cpresources/tempassets which doesn't exist any more.

I can't see how the code in the docs could be used in the email.html override file.

This is from the docs: (https://sprout.barrelstrengthdesign.com/craft-plugins/forms/docs/examples/front-end-file-uploads)

{% set resume = object.resumeAssetFieldHandle.first() %}
Resume: {{ resume.getUrl() }}

But that doesn't work for me. Presumably resumeAssetFieldHandle is just an example field name but I don't know what the object is.

I have (after line 44)

{% if field.handle == 'uploadFile' %}
{{ value[0].getUrl() }}
{% endif %}

Which gives me the temp link.

Any pointers to how I can get the permanent link?

Thanks!

I was adding {slug} in the upload location. This worked for the final file but seems to trigger the behaviour where it links to the temp file.


What do multiple columns of a record being set to unique mean? Does the following mean that both columns or the combination of columns needs to be unique?

public function defineIndexes()
{
    return [
        ['columns' => ['productId', 'productTypeId'], 'unique' => true],
    ];
}

It means that no combination of those two columns can be the same in the table stated in the getTableName() of your record.


Problems with Localized Site Navigation I`ve got a multilingual site (DE/EN) with a Structures section (pages) and one Single for the homepage.
In general.php I set up my localized site as described in the docs for a multi-environment config. German at the top level; English from en/ subfolder:
'domain.dev' => array(
    'siteUrl' => array(
        'de' => 'http://domain.dev/',
        'en' => 'http://domain.dev/en/',
    ),
),

Within my public html folder I copied .htaccess and index.php to en/ and added define('CRAFT_LOCALE', 'en'); to index.php
Navigating to domain.dev shows the german pages:

Seite 1
Seite 2
Seite 3

Changing the URL manually to domain.dev/en/ shows their right translations

Page 1
Page 2
Page 3

and also their right links, e.g. http://domain.dev/en/page-1
BUT following the link to domain.dev/en/page-1 the german content shows up again and the navigation switches back to german.
{% set pages = craft.entries.section('pages').level(1) %}

        {% for page in pages %}

{{ page.getLink() }}

        {% endfor %}

Going to any other english page (e.g. domain.dev/en/page-2) doesn't show up the english content (a translatable field) at all but neither the german content. So I think there is something wrong with my localization setup. Any ideas? Thanks much!

UPDATE
I set up a new craft installation and also a Localized Site as described in the docs.
When defining the site URLs this way everything works like a charm:
return array(
    'siteUrl' => array(
        'de' => 'http://craft.dev/',
        'en' => 'http://craft.dev/en/',
    ),
);

in combination with my multi-environment config it is not working.
return array(
    'craft.dev' => array(
        'siteUrl' => array(
            'de' => 'http://craft.dev/',
            'en' => 'http://craft.dev/en/',
        ),
    ),
);

So I think my config is missing something to transmit the locale the right way?
Is there another way to set up a localized site with multi-environment config?

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

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


Translating Static Text in Craft3 I know that static text translations in still possible but where you put those translations has changed. According to the documentation the folder structure should look like this:

translations/
  en-US/
    app.php
     site.php

but what I can't figure out is where exactly do I put the translations folder. Does it go in the craftcms in vendor?

Just put it on the same level as where the other folders reside, just like:

config/...
storage/
templates/
vendor/...
web/...


Handoff to Paypal Express with Craft Commerce I'm running into issues handing off a cart transaction to Paypal Express. I've set the paymentMethodId correctly on the cart, but when I submit to commerce/payments/pay I am only getting redirected to my cart page and nothing is showing in the Commerce debug logs.

Aside from having cart items and a paymentMethodId, is there anything else required for the Paypal handoff? How can I further debug this?

<form method="POST" id="paypal_checkout_form">
  <input type="hidden" name="action" value="commerce/payments/pay"/>
  <input type="hidden" name="redirect" value="/thank-you?oid={{ cart.number }}"/>
  <input type="hidden" name="cancelUrl" value="/shop/cancel"/>
  <input type="hidden" name="orderNumber" value="{{ cart.number }}"/>

  {{ getCsrfInput() }}
</form>

There is most likely some error in your configuration, or what you're sending to the cart.

The following code (when in devMode) will show you any errors that are coming back from Commerce/Paypal when you're redirected back to the cart:

   {# SHOW ANY ERRORS IF THERE ARE ANY! #}

{% if craft.config.devMode and (craft.session.hasFlash('commerce') or craft.session.hasFlash('notice') or craft.session.hasFlash('error')) %}

    {% set isErrors = true %}
    {% set commerceFlash = craft.session.getFlash('commerce')|join('|') %}
    {% set noticeFlash = craft.session.getFlash('notice')|join('|') %}
    {% set errorFlash = craft.session.getFlash('error')|join('|') %}

    Commerce: [{{  commerceFlash }}]
    Notice: [{{  noticeFlash }}]
    Error: [{{  errorFlash }}]

{% endif %}


Plugin variables class versus twig functions/filters class Is there a particular school of thought on which is best to use?

They both appear to offer the same thing - exposing data and functionality to templates.

The following answer is all personal opinion of course, but here's a key quote from the docs:

  Many of your template variable methods will likely be simple wrappers for your service API methods.

If you look at Craft's built-in Variables, they're all about exposing data. Personally, I like to think of Variables as template APIs.

Twig Filters, on the other hand, is all about modifying data (e.g. capitalizing strings, rounding numbers, formatting dates, sorting arrays etc). If you compare Craft's built-in Variables to its Filters, I think the distinction between the two starts to become fairly clear.

To exemplify:

Bad use of Variables:

{% set sortedEntries = craft.myPlugin.sortByAwesomeLevel( entries ) %}
{{ craft.myPlugin.makeEntryTitleAwesome( entry.title ) }}

The above template code use Variable methods to modify data already present in the template. It works, but it looks pretty convoluted and doesn't really make sense, neither from a Twig nor Craft point of view. Here, using Filters would be much more appropriate:

{% set sortedEntries = entries | sortBy( 'awesomeLevel' ) %}
{{ entry.title | makeAwesome }}

Good use of Variables:

{% set awesomeEntries = craft.myPlugin.getAwesomeEntries %}
{% set sortedAwesomeEntries = craft.myPlugin.getAwesomeEntries( { 'sortBy' : 'awesomeLevel' } ) %}

Here, MyPlugin exposes a "template API" method called getAwesomeEntries. The only thing it does, is to pull entries that are awesome, optionally taking an arguments object for sorting or the like. Obviously, this would not be feasible to implement as a Filter:

{% set awesomeEntries = entries | getAwesomeEntries %}

In short – if you need to expose data, use a Variable. If you need to modify data, use Filters.


striptags not removing  tag? I've seen how you can remove html tags with twig in other posts here so I am using:

{{ product.intro|striptags('
')|raw }}

To remove the
 tag that redactor adds automatically. However for some reason it is not removing it. Anyone have any ideas. Have I missed something glaringly obvious?

Cheers

Actually, the striptags filter (which is just a wrapper for the PHP strip_tags function) removes all HTML tags except the ones you pass in.

In other words, if you want to remove
 tags, just use the striptags filter without any parameters:

{# Will remove all HTML tags #}

{{ product.intro|striptags|raw }}

If there are other tags you want to retain, you'll need to pass those in:

{# Will remove all tags except
 and  #}

{{ product.intro|striptags('
')|raw }}

For a different take on stripping tags, you can use the Retcon plugin (which I wrote). With Retcon, you can remove all
 tags (and only
 tags; retaining their contents as well as all other tags) easily by using the retconChange filter:

{{ product.intro|retconChange('
', false) }}


Update an order afterwards Have to update an order afterwards cause the client can choose a retail partner.

<form method="post" name="submitOrder" style="width: 100%" onkeypress="return event.keyCode != 13;">
  <input type="hidden" name="action" value="commerce/cart/update-cart">
    {{ redirectInput('s/partner?number=' ~ number) }}
    {{ csrfInput() }}

    <input type="text" id="retailPartner"
           name="fields[orderCommercePartner][]"
           value="0">

    <input type="submit"
           class="a-button  a-button--black  a-button--bold js-chooseThisPartner"
           style="margin-bottom: 40px;"
           value="{{ 'Choose this partner' | t }}">
</form>

That's my form I fill the value fields[orderCommercePartner][] via JS and it's filled.

But the order is not updated. Any Ideas what goes wrong here.

Orders can not be updated after they are completed. The only way around this at the moment is if a plugin used it's own controller action to update the order.

Please submit a feature request here: https://github.com/craftcms/commerce/issues


Questions prior using Craft for the first time Hi Craft CMS community

Short background: I am working for over 10 years with CMS and lately was using ProcessWire (and sometimes WordPress). Both are fine and especially ProcessWire is a really cool CMS for all sorts of things. I've built small to large websites, shops, blogs etc. with it.

However, sometimes I feel like the last 10% of awesomeness are missing :-) and some parts doesn't match my needs. That's the only reason looking for something else and Craft looks quite good (knowing there is nothing fitting 100%).

I read the templating docs and those for plugin development. But there are some questions left.

There is no MVC like system, right? Where do I put (separate) code that is not for frontend output? Like on a calendar where a user can filter what needs to be displayed (aka the controller).
I really couldn't figure out how to create an entry (I think this is something like a page in Craft) from the API not the CP?
Do I need to use plugins for all kind of interaction (like gather user data from a form and save it as an entry or somewhere else in the Craft DB)? Or implementing PayPal or using PHPMailer or creating PDF files etc.

I consider using it for first time on my next project. Not a simple corporate website, but with a lot of different challenges how to convert clients ideas into a web-project :-) Do you think Craft has a rather steep learning curve like Magento or is something simple to use as WordPress? Maybe here are ProcessWire user with experience on both CMS.

Thanks for reading :-)

While I've got no expierence with ProcessWire, I'm a fairly new Craft user myself, and I have to say, it's been a breeze to work with.

With regards to your questions:

All your separate, custom code goes into a plugin, which has to have a certain structure (can be generated for you at this site). There you can hook into events, make your own controllers for custom actions, ...
Creating an entry from code can be done by working with it's Model/Record classes and saving it.
There's quite some things already in Craft by default, but to handle forms, you'll either have to write your own controller action to capture it, or use a plugin, same goes for using PayPal or creating PDF's. You can also use composer packages with Craft.

While there is a slight learning curve, mainly for plugin development (as you need to know more about Craft's internals than when just creating templates etc...), I found the community around Craft to be one of the best I ever encountered. When stuck, feel free to pose your questions here or on slack :)


Can't access Craft CMS admin in Chrome Canary 63.0.3233.0 I'm not able to login to my local craft cms in google chrome canary, version 63.0.3233.0. I've attached a screenshot of the error message I've received when trying to go to the standard login page. I can log in fine on normal Chrome.

I know Canary is beta software of newer version of chrome, however, if they release this into the wild later on, is it something to worry about? I'm running MAMP free. Is it something that can be fixed with MAMP pro or? Any suggestions most welcome. Thanks :)

Context: https://ma.ttias.be/chrome-force-dev-domains-https-via-preloaded-hsts/

The gist is that Chrome is forcing all .dev domains to use https (SSL) via HSTS.

If you want to continue to use a .dev domain, then you'll need to create a valid self-signed SSL cert and make sure OpenSSL is configured properly on your box.

Alternatively, you can swap to using something like craft.test because .test is reserved to never be used as an official top level domain. https://en.wikipedia.org/wiki/.test


Insert entry into article field (elementselect?) on a user, with the "onBeforeSaveEntry" hook I'm having a hard time inserting new content into an elementselect field for a user.

Here's the code I'm working on so far, inside a custom plugin init()

parent::init();
craft()->on('entries.onBeforeSaveEntry', function(Event $event) {
    $entry = $event->params['entry'];
    $isNew = $event->params['isNewEntry'];

    if ($isNew) {
        $user = craft()->users->getUserById($entry['authorId']);

        $focusList = $user->getContent()->focusList;

        if (!is_array($focusList)) {
            $focusList = array();
        }
        array_push($focusList, $entry);
        $user->getContent()->focusList = $focusList;

        craft()->users->saveUser($user);

    }
});

I'm tring to add a "onBeforeSaveEntry" hook, that first checks if the entry is new.

If it is, add the entry to the authors "focusList" (an article field without limits)

But I can't get it to work. Any suggestions?

The error message I'm stuck with so far:

"CDbCommand failed to execute the SQL statement: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails" is the error message I'm battling

Sweet, solved it.

Changed the line

array_push($focusList, $entry);

to

array_push($focusList, $entry->id);

and it worked! :D

EDIT: NOPE, it did not fully work. This hook overwrites all the other entries, leaving only the most recent inside the list.

This code does work, without overwriting:

parent::init();
craft()->on('entries.onSaveEntry', function(Event $event) {
    $entry = $event->params['entry'];
    $isNew = $event->params['isNewEntry'];

    if ($isNew) {
        $user = craft()->users->getUserById($entry['authorId']);
        $focusList = $user->getFieldValue('focusList');
        $values = [];

        foreach ($focusList as $focusEntry) {
            array_push($values, $focusEntry->id);
        }

        array_push($values, $entry->id);

        $user->setContentFromPost(array(
            'focusList' => $values
         ));
        craft()->users->saveUser($user);
    }
});


Get Age from Date of Birth I have an entry with a dateOfBirth Date/Time Field.

Is it possible to calculate the current age from that field?

I can't find a craft/twig function/filter to calculate the difference between 2 dates.

Craft's Date/Time field extends PHP's DateTime class so (since 5.3.0) you can use the Diff method like so:

yourDateTimeField.diff(now).format('%y')


Validating Date of Birth format from a form field value I'm working a on website project which includes a web form which asks for various personal details, one of the fields on the form is Date of Birth.

The form is being validated by a custom plugin which is using models for validation.

Currently the AttributeType for the Date Of Birth field is defined as AttributeType::DateTime, so bad values just get removed during POST, however it would be nice to try and catch values that fail a date format validation of dd/MM/yyyy so the user can correct it, otherwise the field value will simply be discarded and user will be unaware of this.

What is best way to check and catch that the Date Of Birth field value isn't in the required format? I want avoid any regex related parsing as I'm sure there are better ways to examine the format using other PHP date related functions.

Would it be worth doing some client-side validation first using javascript to check the date of birth field is entered correctly? You can use an onChange event on your field and then split the string on "/" and check each part is within a valid range 0-31, 1-12, 1900-2016.

For serverside checking, you can use strtotime() and check that the return isn't false.


Adding alt tag to image in a rich text field via its Edit button, within a matrix - breaks code link to the image Craft 2.4. Unusual bug. Adding an alt tag to an image within a rich text field via its Edit button, that's in a matrix, works just fine the first time the entry is saved. However, re-saving the entry breaks the code to the image.

This:

img alt="test" src="/resources/images/someimage.png#asset:1844:url"

Becomes this:

img alt="test" resources="" images="" someimage.png#asset:1844:url"=""

Make sure you're on the latest release.  In 2.4.2670, we updated Redactor to the latest so that might have fixed some bugs.
I can't reproduce what you're seeing. The modal that comes up from the Redactor edit image button doesn't have an "alt" field, so I'm not sure where you're seeing that.
If view source and manually add the alt tag, it behaves as expected no matter how many times I save/edit the entry.
Bug reports are better off here. :)


Segment to filter through categories slug I've seen plenty examples of using the uri segment like below, but it ain't working for me, anyone had same sort of issue?

{% set segment = craft.request.segment(2) %}
{% set pageCats = craft.categories('photoCategories').slug('segment') %}
{% set entries = craft.assets.group('photoUpload').relatedTo(pageCats).find() %}

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

It works if I hard code the segment name .slug('skateboards') and the segment does render when {{ segment }} on other areas of the same page.

Try removing the ' ' from segment in line 2

e.g.

{% set pageCats = craft.categories('photoCategories').slug(segment) %}