Setting up routes for AMP template with category-based urls I'm stuck on implementing AMP templates with category-based URLs as I can't find a way to route the different entry types in the Routes function in the CP.

I have a channel title Articles that has two entry types (Lists and Articles) with a URL format {businessCategory.first.slug}/{slug} that uses a primary category for the first segment of the URL.

I've tried */slug/amp as a route in the CP but then I can't change the AMP template for each entry type.

Any help would be greatly appreciated!

You don't strictly need to change the AMP template for each entry type; you can just load the entry in your AMP template via the slug in the URL.

Check out how I did it here: Implementing AMP in Craft CMS


update existing cart via ajax creates new cart Running craft cms 2 as a backend with react as the front end I am able to create a cart via an ajax post request to actions/commerce/cart/updateCart.

However, I'm not sure how to then update that cart. Every request to updateCart creates a new cart.

What do I need to pass to updateCart for it to update instead of create a new cart?

Craft 3
This is how Craft Commerce fetches the Card
if ($orderNumber = $request->getBodyParam('orderNumber')) {
    // Get the cart from the order number
    $cart = Order::find()->number($orderNumber)->isCompleted(false)->one();
}

You have to include an orderNumber parameter
Craft 2
$number = $this->_getSessionCartNumber();

if ($cart = $this->_getCartRecordByNumber($number))
{
    $this->_cart = Commerce_OrderModel::populateModel($cart);
}
else
{
    $this->_cart = new Commerce_OrderModel;
    $this->_cart->number = $number;
}

/**
 * @return mixed|string
 */
private function _getSessionCartNumber()
{
    $cookieId = $this->cookieCartId;
    $cartNumber = craft()->userSession->getStateCookieValue($cookieId);

    if (!$cartNumber)
    {
        $cartNumber = md5(uniqid(mt_rand(), true));
        $configInterval = craft()->config->get('cartCookieDuration', 'commerce');
        $interval = new DateInterval($configInterval);
        $cartExpiry = date_create('@0')->add($interval)->getTimestamp();
        craft()->userSession->saveCookie($cookieId, $cartNumber, $cartExpiry);
    }

    return $cartNumber;
}

I think you'll have to change the cookie


Is it possible to assign fields to entries by category? I want to show some fields depending in the category selected for the entry but within the editing stage. is it possible?

If not, then how can i check if the entry is in a category in the template and output a field group.

thanks ahead!

Could you use the entry types to achieve the same thing?
https://buildwithcraft.com/features/entry-types


Modified A-Z grouping I'm trying to output the alphabet where certain letters are enabled/clickable based on whether any entries from a specific section start with that letter. Here's the UI:

Getting the A-Z is easy enough:
{% set letterArray = 'A'..'Z' %}

And I'm able to get the entries by first letter:
{% set entries = craft.entries.section('myEntries').orderBy('title asc').all() %}
{% set entriesByGroup = entries|group('title[:1]') %}
{% for firstLetter, entriesInGroup in entriesByGroup %}
    ...
{% endfor %}

I just can't figure out how to properly merge them so I can set a class or whatever on the letters that have at least an entry.

When looping over the letters in the range, you should be able to use the keys filter to check if the current letter is in the entriesByGroup array. If it is, you can link it or add a class, etc.
{% set letterArray = 'A'..'Z' %}
{% set entries = craft.entries.section('myEntries').orderBy('title asc').all() %}
{% set entriesByGroup = entries|group('title[:1]') %}

{% for letter in letterArray %}
   {% if letter in entriesByGroup|keys %}
      {# this letter has at least one entry, anchor link, add a class #}
   {% endif %}
{% endfor %}

{% for firstLetter, entriesInGroup in entriesByGroup %}
   {# your alphabetical entry listing %}
{% endfor %}

I do something similar here on the CraftQuest Archive page but with a slightly different approach (here's a video on it).


Craft 3: Recognize cookies created in Craft 2 In Craft 2, we could set a cookie like this...

craft()->userSession->saveCookie()

... and that would make it a state cookie. This thread describes it pretty well. Essentially, you would end up with a cookie whose name began with a hashed string.

  b72b7553c36d6600e9aeb6c40513deb8MyCookie

However, it seems like that behavior has been largely removed in Craft 3. When I try to save a cookie now, I do it more like this...

$cookie = new Cookie();
$cookie->name = $cookieName;
$cookie->value = $cookieValue;
$cookie->expire = time() + $lifespan;
Craft::$app->getResponse()->getCookies()->add($cookie);

... which doesn't create a state cookie. The cookie name is very simple.

  MyCookie

Generally speaking, that doesn't bother me. But I worry about compatibility issues with the Craft 2 version of my plugin. It's somewhat important that cookies from the old system are recognized when Craft is upgraded.

What is the solution for this? How do I ensure that my old cookies are recognized properly, and/or continue saving this data using the original hashed format?

After a lot of trial & error, it turns out this is not possible. (At least, not by me.)

I was able to retrieve the raw Craft 2 cookie data using the following code...

// Generate hash of Craft 2 cookie
private function _getCraft2CookieHash()
{
    $newBasePath = Craft::$app->getBasePath();
    $oldBasePath = str_replace('vendor/craftcms/cms/src', 'app', $newBasePath);
    $appId = sprintf('%x',crc32($oldBasePath.'Craft'));
    return md5('Yii.Craft\UserSessionService.'.$appId);
}

// Get existing Craft 2 cookie data
public function getExistingCookieData()
{
    // Get name of Craft 2 cookie
    $craft2CookieHash = $this->_getCraft2CookieHash();
    $craft2CookieName = $craft2CookieHash.'MyCookie';

    // If Craft 2 cookie exists
    if (isset($_COOKIE[$craft2CookieName])) {

        // Get value of Craft 2 cookie
        $cookieValue = $_COOKIE[$craft2CookieName];

        /**
         * THIS IS WHERE IT ALL FELL APART
         * The cookie data is too highly encoded.
         */

    }
}

I was able to correctly determine the hash which makes up part of the Craft 2 cookie's name. Keep in mind, this only works if the site's folder structure did not change. The docs give you two different ways to upgrade the site from Craft 2, and this hash-detection logic will only work if you choose to "keep your current directory structure".

However, things really fell apart when trying to get the actual data from the cookie. The data is encoded in some very complex ways. In Craft 2, it uses a complicated function called computeHMAC which goes way beyond my understanding of security. There is no equivalent function in Craft 3 (and if there was, it would probably operate quite differently).

Sadly, I have to throw in the towel and admit defeat here. Backwards engineering the computeHMAC function is more than my puny brain can handle. :(


Craft 3: get enabled sites of an entry I'm looking for a way to list all the enabled sites for a given entry.
 I couldn't find some sort of getEnabledSites method that's similar to the available getSupportedSites.  The latter only returns the siteId and enabledByDefault properties.

Note that I'm doing this within the Element API plugin.

Totally untested but this should work

$enabledSiteIds = (new Query())
    ->select('siteId')
    ->from('{{%elements_sites}}')
    ->where([
        'enabled' => true,
        'elementId' => $elementId
    ])
    ->column();

You might want to join the elements and entries table in order to gain only elements where elements.enabled is true too (and check the expiry date), otherwise you'll receive disabled entries


Title vs Heading in Fresh Install? In a fresh installation the 'Home Page' seems to make use of the custom 'Heading' field whilst the 'News' channel makes use of the 'Title' field.

What is the advantage of using the 'Heading' field over the 'Title' field?

The short answer is, we should probably update that :)

The long answer is:

The homepage is a “Single” section, and originally, Singles couldn’t have dynamic Title fields like Channel and Structure sections; their titles were static, based on the section’s name. So in this case, that Homepage entry’s title was “Homepage”, and the only way to change that would have been to go into the section’s settings and change its name from there. So, back then, if you wanted to give a Single a “Title”-esque field, it had to be a custom one. Which is what that Heading field is – a custom Plain Text field.

As of Craft 2.2, however, Singles can now have dynamic Title fields. So at that point we should have updated the default fields to stop giving that Homepage section a custom Heading field.

Hope that clears things up a bit. I’ll go ahead and make that change for the next release.


Stop Redactor automatically creating hyperlinks Each time I write a link such as www.link.com Redactor automatically turns it into an active hyperlink. Is there a way to turn this function off?

Use the autoparse option to deactivate that behaviour in the redactor configs

Go to: config/redactor/ and add this I believe (untested):

{
  "whatever": true,
  "autoparseStart": false
}


Output loop position number Good Evening,
This is probably something really simple, but I need to output the position of the entries in a query within the loop
{% set relatedEntries = craft.entries().section('memories').limit(10).orderby('RAND()') %}

{% for asset in relatedEntries %}

 **LOOP NUMBER HERE**  {{ asset.title }}

{% endfor %}

I want it to add the number between 1 and 10 depending on its position
Any help would be appreciated

You can use Twig's loop variable (docs).
{% for asset in relatedEntries %}

    {{ loop.index }}  {{ asset.title }}

{% endfor %}


Assign category through a plugin I am importing data into Craft. I happen to know that the id for my desired category is 22. The category is not being saved.

Here is my code.

    $entry = new EntryModel();
    $entry->sectionId   = 3; // 3 is Episode Section
    $entry->enabled     = true;
    $entry->authorId    = 1;
    $entry->slug = $slug;
    $entry->postDate = $postDate;
    $entry->getContent()->title = $title;
    $entry->getContent()->body = $body;
    $entry->getContent()->summary = $summary;
    $entry->getContent()->metaDescription = $summary;
    $entry->showName[] = 22;

Where showName is the category handle of my category field.

Okay, I think I figured it out. 1st, I added the getContent()

I changed

    $entry->showName[] = 22;

to

    $entry->getContent()->showName = 22;

I think the problem is that the category we had set up only allowed for a single value and I was responding with an array.

Someone please correct me if am wrong.


Use FeedMe with a dynamic URL The list of entries I need to grab is available here:

http://arcresources.mediaroom.com/api/newsfeed_releases/list.php?format=json

Each individual entry is available at a unique URL, by adding an ID, like so:

http://arcresources.mediaroom.com/api/newsfeed_releases/get.php?format=json?id=n

Is there some way to get FeedMe to create entries for every ID from the list URL, using the get URL?

There's currently no way to achieve this with Feed Me. A single feed would represent a collection of items to be imported as elements/entries.

One method your could consider is setting up a feed for a single entry, then use the optional url parameter when calling it via the direct feed URL. This overrides the URL used in your feed settings with the one you provide.

This is described https://verbb.io/craft-plugins/feed-me/docs/feature-tour/trigger-import-via-cron


DRY variable setting across templates (macro for variable?) I have a need for something like the following:
{# Template A #}
    {# Do X that sets variable x #}
    {# Do Y that sets variable y #}
    {# Pass x and y into A include partials #}

{# Template B #}
    {# Do X that sets variable x #}
    {# Do Y that sets variable y #}
    {# Pass x and y into B include partials #}

The logic for X and Y is the same in templates A and B.
Is there a way to write each once in some kind of dedicated partial and place them in templates A and B, something akin to return in a JavaScript function?
I'm not sure there is. I think that macros only produce front-end output. And so I have to duplicate the logic in each template. Is that right?

As you noted in your comment, the Twig Perversion plugin will do exactly what you need. It allows you to return a value from a macro, which isn't typically something that Twig permits.
Personally, I'd consider it to be fairly safe to rely on this plugin for a few reasons. Marion is a long-standing and trusted developer in the community, the plugin is relatively simple, and could easily be replaced with a small custom module if it ever went defunct. It also doesn't touch your data, so removing it in the future won't cause any problems.


List only those months that have entries I setup my archive using the Craft demo.  I have a page for each year.

I use MixItUp,(think Isotope) to allow a user to filter entries by month. There are simple hard coded buttons for each month.

How can I loop through the entries and create a button for only those months that have entries?

Update.  I have a loop that pulls all the entries for a given year.  I then use MixItUp (think Isotope) to filter the entries by month.

There is a button for each month that triggers MixItUp.  I want to make the creation of these buttons dynamic.  That is, I want to create a loop that generates a button for only those months that contain entries and create a class with the month's name that corresponds with the month in the class names of the entry cards.

For any given year, the loop would create 1-12 buttons.

{% for month that has > 0 entries %}

<button type="button" class="btn btn-outline-secondary btn-lg"   data-mixitup-control data-filter=".February">Feb</button>

{% endfor %}

Thanks

{% set date = (date()).modify('first day of january 00:00:00') %}
{% for month in 1..12 %}
    {% set endOfMonth = clone(date).modify('last day of this month') %}
        {% set exists= craft.entries
            .postDate(['and', '>=' ~ date.format('-.m-d H:i:s'), '<=' ~ endOfMonth.format('Y-m-d H:i:s') ])
            .exists()
        %}

    {% do date.modify('first day of next month') %}
{% endfor %}

loop all months and check if there are entries in this month or not


Invalid username or password, errorCode:0 but I'm using correct credentials When I try to log in to CP as admin with correct credentials I'm getting "Invalid username or password" error and the response contains errorCode: 0 (I'm guessing CBaseUserIdentity::ERROR_NONE)

Weird part is that when I pull the same database to my local dev I can login using same credentials.

Only thing I can see in the logs is:

  Tried to restore session from a cookie, but the given login name does not match the given uid. UID: bd098373-8d73-4f6c-8326-9f5a2825f5a4 and loginName: Guest.

PHP can write into /craft/storage folder. I tried clearing out craft_session table, overridePhpSessionLocation => false and removing craft/storage/runtime/, nothing helped.

I'm using PHP7.1 and MySQL 5.7.

Ok I've solved the issue. PHP was trying to save the sessions into a non-existing directory.

To check the current session path, I've added var_dump(session_save_path()); in Craft's /public/index.php (was set to /var/lib/php-fpm/session).

Fix was to update session.save_path setting in the php.ini to point to the right directory with correct permission.

Hope this helps someone in the future.


Sprout forms AJAX submission giving Template not found I am able to capture submissions from a regular HTML form, however if I replicate the POST with JSON I get the following "Template not found" error.

Template not found: sprout-forms/entries/save-entry
1. in /var/www/Applications/vendor/craftcms/cms/src/controllers/TemplatesController.php
at line 70 61626364656667686970717273747576777879
  * @param string $template
  * @param array $variables
  * @return Response
  * @throws NotFoundHttpException if the requested template cannot be found
  */
 public function actionRender(string $template, array $variables = []): Response
 {
     // Does that template exist?
     if (!$this->getView()->doesTemplateExist($template)) {
         throw new NotFoundHttpException('Template not found: ' . $template);
     }

     // Merge any additional route params
     $routeParams = Craft::$app->getUrlManager()->getRouteParams();
     unset($routeParams['template'], $routeParams['template']);
     $variables = array_merge($variables, $routeParams);

     return $this->renderTemplate($template, $variables);
 }

2. craft\controllers\TemplatesController::actionRender('sprout-forms/entries/save-entry', [])

....

11. in /var/www/Applications/web/index.php at line 21 – yii\base\Application::run() 15161718192021
                     (new Dotenv\Dotenv(CRAFT_BASE_PATH))->load(); }   // Load and run Craft define('CRAFT_ENVIRONMENT',
getenv('ENVIRONMENT') ?: 'production'); $app = require
CRAFT_VENDOR_PATH.'/craftcms/cms/bootstrap/web.php'; $app->run();

I have disabled CSRF for now in the hope of taking that out of the equation.

I believe I have replicated the HTML form request with a JSON POST using Postman but am hitting a dead-end. Any assistance with debug steps, or a sample Postman config to a working solution would be hugely appreciated.

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

{% hook 'sproutForms.modifyForm' %}

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


Best way to include attachments using EmailService [Craft Plugin]? I've got Email Service working correctly (http://buildwithcraft.com/docs/apis/emailservice) but what's the best way to include attachments when using this service?

Here's what I've got so far:

    $email = new EmailModel();
    $email->subject = "Thanks!";
    $email->htmlBody = "
Congratulations!
htmlBody .= "
Hello World
";
    $email->fromEmail = "email@domain.com";

I see there is $email->addAttachment but I'm not sure what variables to include to make it pass through the service.

Anyone have any examples?

In craft/app/models/EmailModel.php the function docblock describes the params:

/**
 * Adds an attachment from a path on the filesystem. Returns false if the file could not be found or accessed.
 *
 * @param string $path Path to the attachment.
 * @param string $name Overrides the attachment name.
 * @param string $encoding File encoding (see $Encoding).
 * @param string $type File extension (MIME) type.
 * @throws phpmailerException
 * @return bool
 */
public function addAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream')
{
    $existingAttachments = $this->attachments;
    $existingAttachments[] = array('path' => $path, 'name' => $name, 'encoding' => $encoding, 'type' => $type);
    $this->attachments = $existingAttachments;
}

Is that what you're looking for?


Does setting Enabled = 1 override postDate in front end forms? I have a front end form where I set have

<input type="hidden" name="enabled" value="1">

I also need to set the postDate to a date in the future. Does setting enabled = 1 reset the postDate in all cases? Or should I just forego the enabled form field altogether in favor of Setting postDate?

Setting enabled = 1 will not alter your postDate.

If you were to set a postDate in the future, the entry would simply not show up (by default).
However, if you'd want enabled entries with a future postDate to show up in your template results, use:

{% set futureEntries = craft.entries.status('pending') %}

If you do not use the status criterium, it will default to live, which is all enabled entries with a postDate in the past. So, it all depends on how you display the entries, not so much on how you save them.

Also, see this Craft docs information on status.


Solspace Calendar (2.0.0-b9) returning template not found error in CP In the CraftCMS (3.0.2) control panel > Calendar > Month, when I click on one of my events I get the following error:

Template not found: therapy-wellness/_entry

I deconstructed the link and found that it's trying to pass the calendar name and the entry URL title to the _entry template. Eg.

/calendar-name/my-event-url-title

Obviously the issue is that the template to handle this request does not exist, but I'm not clear on when this stopped working or what to do about it?

Have you checked what values you have for the calendar(s) under the Site Settings: Event URI Format & Template

It's possible you might have something incorrect there. Perhaps the Template path inside the Event URI Format area, instead of a proper value like /calendar_demo/event/{slug}.


Loop through all sites in multisite installation Who knows how to loop through all sites in multisite installation? I want to create kind of drop down menu to switch between websites.
I've found this code inside the backend template but looks like it doesn't works in frontend

{% for site in allSites %}

                {{ site.name|t('site') }}
                {{ site.handle }}
                {{ site.language }}
                {{ site.baseUrl }}
                {% if multiple %}

                {% endif %}

        {% endfor %}

UPD:
Now I can fetch names of websites by their Ids:

      {% set allSitesIds = craft.app.sites.getAllSiteIds() %}
  {% for site in allSitesIds %}
  {% set siteName = craft.app.sites.getSiteById(site) %}
  {{siteName}}
  {% endfor %}

Nikolay,

As I responded in the slack, I will respond here in case anyone else has this question.

In the template you can access this information like so:

SiteUrl: {{ siteUrl }}
Langauge: {{ craft.app.language }}
Handle: {{ craft.app.sites.currentSite.handle }}

I'm not entirely positive how to loop the sites in the template but you can get a sites object in PHP by running the following in a controller somewhere or in the init() method of any plugin that is installed:

$sites = Craft::$app->getSites();
var_dump($sites);
exit;

This will output the structure of the sites object. Baring this you can look through the craft source / docs to find the details on the site object that returns. There should be a method for getting sites by id or by handle; $sites->getSitesByID() or $sites->getSitesByHandle() but I have not double checked this so you'll have to try it or look it up. If there is not a method then it should be accessible via an array property like $sites->sitesByHandle or $sites->byHandle. Again you'll have to double check on this.

By the way, that functionality should translate to the template version of the sites object craft.app.sites so you should be able to do:

{% set sites = craft.app.sites.getSitesByHandle() %}

Or something like that anyway.

Once you figure it out feel free to update this to reflect the proper methods / properties :)


Looking for a private commenting solution for member area I've had a look through some previous posts and the craft docs and it doesn't look like anyone has done anything similar to what I want.

Essentially I have a 'client area' where a user can log in and just see photos and videos that are set on their profile (added by the admin). This all works great but I require functionality so the user can add a comment to said video or photo. I know solutions such as Disqus have been suggested but I can't see away of making them private and locked down so other guests and members cannot get access to the comments.

Does anyone know of any plugins, or methods through Craft that could be a possible solution or starting point to a solution?

Thanks!

Something like this should work, but keep in mind there are lot's of ways to accomplish this. Without knowing your requirements, I'll assume you want an index page of assets, that link to an asset detail page. The detail page would show all comments and provide a form to add new comments.

On your assets index page (i.e. '/clientarea/lightbox'):

{% requireLogin %}

{# show user profile information (if needed) #}

    {{ currentUser.firstName }} {{ currentUser.lasName }}

{# loop through images in Assets field #}

Images

    {% for image in currentUser.assetsFieldHandle %}

            {# display image, title and link #}

            {{ image.title }}

            View image

    {% endfor %}

{# repeat for videos, etc #}

In your asset detail page (i.e. 'clientarea/lightbox/media/123' ). Note: to get this uri, you can either create these folders in your templates folder (i.e. 'clientarea/lightbox/media/_entry.html'), or create a custom route.

{% requireLogin %}

{# fetch image #}
{% set imageId = craft.request.lastSegment %}
{% set image = craft.assets.id(imageId).first %}

{# check whether image exists, otherwise redirect 404 #}
{% if not image %}
    {% redirect 404 %}
{% endif %}

{# check whether they are authorized to view this asset #}
{% set authorized = false %}
{% set authorizedImages = craft.assets.relatedTo(currentUser) %}
{% for authorizedImage in authorizedImages %}
    {% if authorizedImage.id == image.id %}
        {% set authorized = true %}
    {% endif %}
{% endfor %}

{# if not authorized, redirect to 401 #}
{% if not authorized %}
    {% redirect 401 %}
{% endif %}

{# show user profile information (if needed) #}

    {{ currentUser.firstName }} {{ currentUser.lasName }}

{# display image details #}

    {# display image and title #}

    {{ image.title }}

{# fetch comments from the 'clientComments' section that are related to this image #}

    {% set comments = craft.entries.section('clientComments').relatedTo(image) %}
    {% for comment in comments %}

{{ comment.commentTextFieldHandle }}

    {% endfor %}

{# display a form to add a new comment #}

    <form method="post" accept-charset="UTF-8">
        {{ getCsrfInput() }}
        <input type="hidden" name="action" value="entries/saveEntry">
        {# reload the current page on successful form submission #}
        <input type="hidden" name="redirect" value="{{ craft.request.path }}">
        {# section id for 'clientComments' #}
        <input type="hidden" name="sectionId" value="2">
        <input type="hidden" name="enabled" value="1">

        {# hidden field to save the image id #}
        <input type="hidden" name="fields[commentAssetsFieldHandle]" value="{{ image.id }}">

        Comment
        <textarea id="body" name="fields[commentTextFieldHandle]"></textarea>

        <input type="submit" value="Add comment">
    </form>

You will likely also need to add some checks for the asset type, in order to determine how to display the asset. But you get the general idea.

You will also need to make sure that they have permission to create entries in the clientComments section (but not view or edit other peoples entries).

And if the image or video is displayed on more than one user's profile, then you will also need to factor in the author when searching for comments. Either that, or also add a related users field to the comments section, and then search for comments related to both image and currentUser.


Help selecting an e commerce framework So i have a client that wants fast e commerce store, currently I've narrowed it down to 2 solutions.
Headless Magneto CMS with a Magneto PWS studio as the front-end. Its based on react which should be fast and Magento's search uses elastic search which I've read is faster than MySQL.
The second is a simpler solution, Craft Commerce. Is a flexible and light commerce platform.
However how will a "light" PHP/MySQL platform compare to a react front-end with a "heavy" back-end using elastic search back-end.

At the risk of being too general/closed for off-topic, before you choose any platform, I would ask these questions:

What sort of functionality  does your client require—now or in the future?
What kinds of products will the store support (eg bundles, custom products, variants, donations, etc).
What sort of budget / developer support can the client support or is required?

In general, Craft is the more nascent/new product so if your team's dev chops aren't familiar with Commerce, there can be a learning curve.
Magento does a lot of the box and if you need to hook into some obscure (or not so obscure) service, Magento probably already has a plugin for it. It has a bigger ecosystem but that doesn't mean Craft isn't up to the task.
Shopify can also be an option depending on what you're trying to do.
In general, Craft/Commerce really excels at customized e-commerce. If your client's needs are modest, for example selling simple products without customization, Shopify might actually be a better fit long term. However when you start to get into more niche businesses where there's customized shipping or products, the the tables tip more in favor of Craft.
Speed
You question also asks about speed. Fast is a relative turn. A lot is going to depend on 1) server infrastructure and 2) your own code.
Also:

What does a performance budget look like?
How many visitors/users are you expecting? Where are they located?
How will you measure the solution?

Compared to Magento, Craft is pretty light-weight. Magento is not known for being resource-friendly, however there is probably more documentation on how to make it speedy.
If you go with something like Shopify, you don't have to worry about infrastructure—which is one of the reasons it's popular.
Also related
Why choose Craft Commerce over Magento


How to display all fields belonging to current entry? How do I modify a template to include a loop that displays all custom fields that I added to the field group that the current entry belongs through? I know how to display the fields individually by calling their name, but how to display all fields belonging to the group?

Field groups are not specific to a particular channel or channel entry. They are just an arbitrary organization within the control panel for ease of use. What you would be looking for are the fields defined for the particular field layout for that entry. I.e.:

{# loop through the fields in the entries fieldLayout Model #}
{% for fieldLayoutField in entry.getFieldLayout().getFields() %}

    {# get the field Model from the fieldId #}
    {% set field = craft.fields.getFieldById(fieldLayoutField.fieldId) %}

    {# print the field handle and the field content  #}
    {{ field.handle }} : {{ entry.getContent()[field.handle] }}

{% endfor %}

By the way, there is an excellent plugin called 'Inspector' written by Adrian McNeal that displays all methods/attributes/properties of an object or variable, which can be very useful for figuring out what your dealing with.

UPDATE: It has been brought to my attention thatfieldLayoutField.fieldId has been discontinued in favor of fieldLayoutField.id. While not tested, if the above does not work, please try the following instead:

 {% set field = craft.fields.getFieldById(fieldLayoutField.id)


How to use different date format in front end form? I have a date field on a front end form, currently with this HTML:
<input class=" date-picker startDate" type="text" id="startDate" name="fields[startDate]" value="">

I use a JQuery date-picker and have set its format to dd/mm/yyyy
The date displays in the field this format correct, but upon saving no date is saved. I guess its due to the format not being Crafts yyyy-mm-dd because if I set the date-picker format to this, it does save it OK. BUT I obviously dont want to display my dates like this.
How can I display dates in correct human date format in the fields, and save them to the DB correct? Do I need to process all dates in PHP in a plugin to the correct format first?
The field in Craft admin for the entry displays d/m/y OK and that saves.
Thanks

For me, saving dates as a timestamp seems to do the trick to correctly save to the date field in Craft. You can still use the datepicker and have the human readable date, just use the altField and altFormat options (https://jqueryui.com/datepicker/#alt-field) to fill a hidden field with the timestamp that gets submitted.


Organizing Entry, Section, and Category hierarchies I have a site with three broad sections of content:  Humanities, Business, and Music.

Within each of these are sub-sections. Under "Humanities", for example, is Politics, History, Economics, etc. Within these are more sections as well.

What's the correct way to organize such a hierarchy?

For each index page, I want all of the posts for the entire hierarchy below it. So going to /humanities would have a feed of all of the latest entries for every section below it. Navigating to /humanities/politics/ would show just politics and its subsections.

I've looked at using categories, but want the url structure to reflect all the way down the chain. Is this possible?

This is Craft CMS, so there is no 'correct' way of doing it. With the routing and slug manipulation you can achieve this is many ways.

However, to me it feels like 'Categories' would be the way to go. To get your URL hierarchy that you have suggested, you'd need to set the following for the Category URI format in Settings > Categories:

{% if object.level == 1 %}{slug}{% else %}{parent.uri}/{slug}{% endif %}


SEO titles/descriptions for tags and archive pages I have a blog setup with a Categories, Archive and Tags.

In my _layout template I've been using the following to pull in SEO titles from fields, or Page/Category Titles is that's not been defined.

{% if entry is defined %}
    {% set seoTitle = entry.seoTitle %}
    {% set seoDescription = entry.seoDescription %}
    {% set seoImage = entry.seoImage %}
    {% set seoType = entry.seoType %}
    {% set title = entry.title %}
    {% set url = entry.url %}
{% endif %}

{% if category is defined %}
    {% set seoTitle = category.title %}
    {% set seoDescription = category.title %}
    {% set seoImage = category.seoImage %}
    {% set seoType = category.seoType %}
    {% set title = category.title %}
    {% set url = category.url %}
{% endif %}

<title>{{ siteName }} - {% if seoTitle is not empty %}{{ seoTitle }}{% else %}{{ title }}{% endif %}</title>
<meta name="description" content="{% if seoDescription is defined %}{{ seoDescription }}{% else %}{{ title }}{% endif %}"/>
{% if url is defined %}<link rel="home" href="{{ url }}" />{% endif %}
<meta name="twitter:card" content="summary" />
{% if url is defined %}<meta property="og:url" content="{{ url }}" />{% endif %}
<meta property="og:title" content="{% if seoTitle is not empty %}{{ seoTitle }}{% else %}{{ title }}{% endif %}" />
<meta property="og:description" content="{% if seoDescription is defined %}{{ seoDescription }}{% else %}{{ title }}{% endif %}" />
{% if seoImage is defined %}
    {% for image in seoImage %}
        <meta property="og:image" content="{{ image.getUrl()}}" />
    {% endfor %}
{% endif %}

How should I approach this for the archive and tag pages as simply doing something like the below doesn't work?

{% if tag is defined %}
{% set seoTitle = tag.title %}
....
{% endif %}

The better approach in my opinion is to declare the variables in the corresponding templates rather than in the _layout template

Layout.twig

{% if seoTitle is not defined or seoTitle is empty %}
    {% set seoTitle = config.seoTitle %} <-- fallback if nothing is defined
{% endif %}
<title>{{ siteName }} - {{ seoTitle }}</title>

_entry.twig

{% extends 'layout' %}
{% set seoTitle = entry.seoTitle %}

_category.twig

{% extends 'layout' %}
{% set seoTitle = category.seoTitle %}

_someOtherTemplates.twig

{% extends 'layout' %}
{% set seoTitle = 'Some hard coded strings....' %}

and so on. That way you can define seoTags based on custom properties as well otherwise it would be difficult to determinate tags on dynamic template routes without an entry or a category


Getting the first and last days of a multi-day event - Solspace Calendar Is there a way to get the first and last days of a multi-day event? I want to be able to style the first and last days differently. I don't see anything like this in the docs.

This is in Craft 3 and Calendar 2.0.17

Within the context of calendar.month, if you check out the demo templates, we style the beginning and end of multi-day events with the following code:

{% if event.multiDay %}
    {% set classes = classes ~ " multi_day" %}
    {% set classes = classes ~ (day.containsDate(event.startDateLocalized) ? " first_day") %}
    {% set classes = classes ~ (day.containsDate(event.endDateLocalized) ? " last_day") %}
{% endif %}


PHP warning with composer on MacOS Mojave: Failed to open stream: No such file or directory I am working on a plugin in Craft:3.4. I get this error while trying to install the plugin in the CP.
yii\base\ErrorException: include(/app/vendor/composer/../wittsstratts/craft-company/src/Company.php): failed to open stream: No such file or directory in /app/vendor/composer/ClassLoader.php:444
Stack trace:
#0 /app/vendor/craftcms/cms/src/web/ErrorHandler.php(74): yii\base\ErrorHandler->handleError(2, 'include(/app/ve...', '/app/vendor/com...', 444)
#1 /app/vendor/composer/ClassLoader.php(444): craft\web\ErrorHandler->handleError(2, 'include(/app/ve...', '/app/vendor/com...', 444, Array)
#2 /app/vendor/composer/ClassLoader.php(444): include()
#3 /app/vendor/composer/ClassLoader.php(322): Composer\Autoload\includeFile('/app/vendor/com...')
#4 [internal function]: Composer\Autoload\ClassLoader->loadClass('wittsstratts\\co...')
#5 [internal function]: spl_autoload_call('wittsstratts\\co...')
#6 /app/vendor/craftcms/cms/src/services/Plugins.php(873): is_subclass_of('wittsstratts\\co...', 'craft\\base\\Plug...')
#7 /app/vendor/craftcms/cms/src/services/Plugins.php(478): craft\services\Plugins->createPlugin('company')
#8 /app/vendor/craftcms/cms/src/controllers/PluginsController.php(50): craft\services\Plugins->installPlugin('company', NULL)
#9 [internal function]: craft\controllers\PluginsController->actionInstallPlugin()
#10 /app/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array(Array, Array)
#11 /app/vendor/yiisoft/yii2/base/Controller.php(157): yii\base\InlineAction->runWithParams(Array)
#12 /app/vendor/craftcms/cms/src/web/Controller.php(178): yii\base\Controller->runAction('install-plugin', Array)
#13 /app/vendor/yiisoft/yii2/base/Module.php(528): craft\web\Controller->runAction('install-plugin', Array)
#14 /app/vendor/craftcms/cms/src/web/Application.php(290): yii\base\Module->runAction('plugins/install...', Array)
#15 /app/vendor/craftcms/cms/src/web/Application.php(558): craft\web\Application->runAction('plugins/install...', Array)
#16 /app/vendor/craftcms/cms/src/web/Application.php(269): craft\web\Application->_processActionRequest(Object(craft\web\Request))
#17 /app/vendor/yiisoft/yii2/base/Application.php(386): craft\web\Application->handleRequest(Object(craft\web\Request))
#18 /app/web/index.php(21): yii\base\Application->run()
#19 {main}

This question is related to this but with a different setup.
Tools:

Docker:19.03.5
Composer:1.10-dev

This might help anyone facing this same issue.
I found the reason for the error was because I was using docker. Composer symlinks the plugin from its physical directory into craft's vendor directory. The plugin directory as a result of this was not mounted into docker container. Thus, craft was not able to locate the plugin directory. All I did to fix this was move the project(plugin) into craft's vendor director.

Composer symlinked the plugin from its physical directory into craft's vendor directory. The plugin directory as a result of this was not mounted into the docker container. Thus, craft was not able to locate the plugin as it wasn't mounted into my docker container. All I did to fix this was move the project(plugin) into craft's vendor director.


Charge plugin: subscription start and end dates not updating for recurring subscription payments I've been using Charge to handle a subscription service on a client site, and for the most part, it's been working well for the past year. Now that a year has gone by, the first set of recurring membership subscriptions are starting to be automatically renewed.

A problem I'm seeing is that the dates displayed using Charge's subscription.currentPeriodEnd template variables are not showing updated dates. They still show the end date for the initial year of the subscription, not the new end date which should be one year past the date of the renewal.

Anyone else experiencing this and can suggest a fix?

In a potentially related issue, the recurring payment is being displayed as "TEST" mode in the UI in Charge. See screenshot:

Not really a solution, I know, but in the absence of any support from the developer on this there may be a workaround.

In my case I've been developing using planIntervals of only 1 day so I can see what's going on. As noted in your question, it never updates to the correct currentPeriodEnd, but it does seem to be updating. It looks like it updates to the end of the next but last payment taken. Here's an example:

I've got three payments taken for this subscriber:

2018-07-26
2018-07-25
2018-07-24

With the last payment being on 26 July, currentPeriodEnd should be 27 July. It isn't. It's outputting 26 Jul, the period end of the next to last payment. Or maybe the actual date the last payment was taken. I'm not sure.

Rather than fix this, I'm probably just going to test for the subscription being active and adding the planInterval to the currentPeriodEnd. But only if more than the initial payment has been made.

{% if charge.subscription.status == "active" %}

    {% if charge.payments | length > 1 %}
        {% set paymentEnd = charge.subscription.currentPeriodEnd | date_modify("+1 day") %}
    {% else %}
        {% set paymentEnd = charge.subscription.currentPeriodEnd %}
    {% endif %}

    {{ paymentEnd | date('j M Y') }}

    {% set daysToRenewal = date(paymentEnd).diff(now).days %}
    {{ daysToRenewal }} days to renewal

    {# Send email to subscriber if exactly 28 days to go #}

{% endif %}


Home page loop once, other pages loop through all I only want one block on the home page, other pages can loop through all of them. Is there a more efficient way to write this?

{% if craft.request.getSegment(1) is empty %}
        {% for block in memberships.memberships.limit(1) %}

            {% for asset in block.logo %}

            {% endfor %}

        {% endfor %}
    {% else %}
        {% for block in memberships.memberships %}

            {% for asset in block.logo %}

            {% endfor %}

        {% endfor %}
    {% endif %}

You could do it this way:

{% set blockLimit = entry.section.isHomepage() ? 1 : null %}

{% for block in memberships.memberships.limit(blockLimit) %}

    {% for asset in block.logo %}

    {% endfor %}

{% endfor %}

entry.section returns the SectionModel for the entry, and isHomepage() tells you whether that section is the homepage. Then you set your limit accordingly.


Craft password encryption When I reset my password with the same password I used before.
I checked the MySQL database the old encrypted password is different from new encrypted password.

Do you guys know why?

That's because Craft follows the standard procedure of hashing passwords with what's called a "salt" as a security measure.

Think about it this way - if a password were hashed without a salt, every instance of the same password would result in the same hashed value.

Example:

Suppose there are two users, Foo and Bar. They both choose password123 as their password. When hashed without a salt, their passwords would look the same after hashing, which is a security flaw.

We can see this by testing it with any hash algorithm:

(I'm using md5 here for readability because it gives a shorter result - do not actually use md5 for anything secure)

password123 becomes 482c811da5d5b4bc6d497ffa98491e38, and - without using a salt - would be stored that way for every user with the password password123.

The implication here is that the system is now vulnerable to a variety of attacks, like Lookup Tables and Rainbow Tables, which depend upon every instance of a password yielding the same hash.

Enter Salts. Salts are psuedo-random strings attached to the user's password prior to being hashed and stored.

In our Foo and Bar example, that would look something like this:

Foo chooses password123. The system generates a psuedo-random "salt" of pg7n6yVBzWJbaxfF, combines them into pg7n6yVBzWJbaxfFpassword123, and then hashes that result to get d026a6847c743e23195cf37db2a66ae9. In addition, Foo's generated salt is stored in the table, so that it can be used to test login attempts.

Bar does the same, but the system generates Am6g4n0JEFdE1poH as his salt. When combined with password123 and hashed, it then yields a different result: 5e7b0bb4842ee8315105a62922c32894.

Both users have the same password, but the final hashed result now has no traceable relationship to the original password in either case. If a malicious party were to try and search for password123 by scanning the database for its hashed equivalent (in our example 482c811da5d5b4bc6d497ffa98491e3), it wouldn't find anything.

The same principle applies to resetting your password - even if you choose the same password, that new instance of the password is re-salted, re-hashed, and stored as something distinct.


Problem pulling Tweets with media using Dukt's Twitter API plugin {% set tweets = craft.twitter.get('statuses/user_timeline', { tweet_mode:'extended' }) %}

{% for tweet in tweets %}

    {% if tweet.extended_entities.media is defined %}
        {% for item in tweet.extended_entities.media if item.type == 'photo' %}

        {% endfor %}
    {% endif %}

{% endfor %}

Anything obviously wrong here? I tested the API with a {{ dump(tweets) }} which seems fine.

This thread describes a similar issue but without a solution.

The return from craft.twitter.get() is not an array of tweets, but a response object, where the actual tweets are nested in an attribute called data.

Not tested, but from looking at the plugin docs, something like this should do it:

{% set response = craft.twitter.get('statuses/user_timeline', { tweet_mode:'extended' }) %}

{% if response.success %}
    {% for tweet in response.data %}
        ...
    {% endfor %}
{% endif %}


Email notifications with attachment when uploading files to s3 I'm attempting to create email notifications with attachments when using Sprout Forms and S3 assets.

Given Sprout Forms 2.1.5 & Craft Pro 2.5.2760

And a form with an Asset field

And default upload location in an S3 bucket

And enable notifications set to true

And enable file attachments set to true

When a user submits a form, no email is sent and the following error is logged in sproutforms.log

Craft\S3AssetSourceType and its behaviors do not have a method or closure named "getBasePath".

Looking into the docs, S3AssetSourceType does NOT have a method named getBasePath, but localAssetSourceType does.

My question is, does sproutforms support notification emails with attachments when using S3?

Sprout Forms v2.3.0 added support for S3 Asset uploads and file attachments.

--

OUTDATED: As of this post, Sprout Forms does not yet support email attachments using S3.

As a workaround, it is possible to override the email.html notification template using Template Overrides and link to or display S3 assets in the way you would provide a link to any asset:

{{ asset.getUrl() }}


Search matrix for blocks with upcoming dates I have a matrix field with one "event" block type that contains several fields. One of those fields is a date field. Is there a way to get just blocks with upcoming dates?

Here’s how you would do that:

{% set futureEvents = entry.myMatrixField.myDateField('>= '~now) %}

{% for event in futureEvents %}
    {{ event.description }}
{% endfor %}

Update:

This actually hadn’t worked as I expected to, but it does as of Craft 2.3.


Programmatically entering data into a table field for an entry I now know that you can enter data into an entry's field by using $event->params['entry']->getContent()->handle

But let's say I have a foreach loop and I want to enter each line into an entry that is a table field. So for example:

foreach ($apigrab['properties'] as $specs) {
    $event->params['entry']->getContent()->specs == ??
}

Obviously each table heading has it's own handle and I don't imagine specs.handle would work in this case, and also how would you prevent it from just overwriting the same line over and over again? Would I have to count how many first and tell it specifically where to go?

Thanks in advance.

When saving data to a Table field, here's the catch... Your field data is being condensed into JSON and stored in a single database table cell.

So ultimately, you'll want to have your Table field data arranged in an array, then use json_encode to prep it for entry into the database.

Here's an example of data for a Table field... This is a hypothetical field containing products, with a Product Name and prices for Small, Medium, and Large...

[
  {
    "col1": "Product #1",
    "col2": "5",
    "col3": "10",
    "col4": "15"
  },
  {
    "col1": "Product #2",
    "col2": "7",
    "col3": "14",
    "col4": "21"
  },
  {
    "col1": "Product #3",
    "col2": "7",
    "col3": "14",
    "col4": "21"
  }
]

An important note... The column names you established when setting up your Table field are not relevant here. Instead, each columnn will be referred to as "col1", "col2", "col3", etc.


Same site name in multiple languages We have a site with multiple languages so I created a site for each language.
I named these according to the language so, one is named "French", another "English" etc.

Now in the backend this is all fine, when creating entries its clear what the language is you are working in.

I soon noticed these are also used in the front-end and that creates some problems. The site name in a template is easily override by adding something like {% set siteName = getenv('SITE_NAME') %}.

But harder to fix are for example the mails send out when creating a account, they now say something like "Thank you for creating an account on English!"

I tried a fix by setting the same site name in the config/general.php, this works, but now all the sites in the site switcher in the backend are the same. So not really a good fix.

Having to set a different name for each site is kinda weird, in most cases the brand name is the same in every language. Google is Google no matter the language.

Anyone who knows a decent way to handle this?

I ended up using the suggestion of Robin Schambach, in front-end templates using the {{ site.group.name }}
E-mail contents can be changed in the admin section, using {{currentSite.group.name}}
Craft 2:
settings -> email -> Messages
Craft 3.0:
settings -> email -> Messages
Craft 3.1:
Utilities -> System Messages


How to conditionally hide particular plugin settings? This answer has given me most of what I need, but I'd like to hide certain settings based on the status of other settings. CP seems to have nice functionality built in for conditionally hiding/showing parameters. For example, when changing a field from Rich Text to Plain Text, several options disappear.

In this case, only if the preceding checkbox is checked do I want it to give an input field for the category field handle.

Here is my /craft/plugins/calendar37/templates/_settings.html file:

{% import "_includes/forms" as forms %}

{{ forms.checkBox({
        label: "Event Hyperlinking"|t,
        id: 'eventClickDestination',
        name: 'eventClickDestination',
        instructions: "If checked, clicking on an event goes to Category page. Otherwise, unchecked it will go an Entry page"|t,
        value: settings.eventClickDestination,
        errors: settings.getErrors('eventClickDestination')
    })
}}

{{ forms.textField({
        label: "Category Field's Handle"|t,
        id: 'categoryFieldHandle',
        name: 'categoryFieldHandle',
        instructions: ""|t,
        value: settings.categoryFieldHandle,
        errors: settings.getErrors('categoryFieldHandle')
    })
}}

Note, I'd like to work out similar functionality with a 3-part radio button, but haven't figured out how to do radio buttons yet.

Thank you!

I'm not sure how to do a 3 way toggle with radio boxes, it might involve writing your own JS... but for the checkbox toggle it's pretty straight forward :)

{{ forms.checkboxField({
    ...
    toggle : 'toggleThis'
}) }}

<div id="toggleThis" {% if settings.eventClickDestination is not defined or not settings.eventClickDestination %} class="hidden"{% endif %}>
  //.. Form input goes in here
</div>

Craft will then take care of the toggling for you when the box is checked/unchecked


Feed Me, skip element I want to skip an element within Feed me after if a condition passes.

So i am listening to the stepBeforeElementMatch event.
Within this event i would have something like this:

if($event->feedData['status'] == "false") {

    // dont import, skip me
}

I couldn't find any way how i would skip this specific element. I am wondering if there is a way to even skip an element?

Ok, so this is the relevant code in the service processing the feed, where the stepBeforeElementMatch is being called:

        // Fire an 'onStepBeforeElementMatch' event
        if ($this->hasEventHandlers(self::EVENT_STEP_BEFORE_ELEMENT_MATCH)) {
            $event = new FeedProcessEvent([
                'feed' => $feed,
                'feedData' => $feedData,
                'contentData' => $matchExistingElementData,
            ]);

            $this->trigger(self::EVENT_STEP_BEFORE_ELEMENT_MATCH, $event);

            if (!$event->isValid) {
                return;
            }

            // Allow event to modify variables
            $feed = $event->feed;
            $feedData = $event->feedData;
            $matchExistingElementData = $event->contentData;
        }

I have not tested this, but by the looks of it, it should be enough to set the $event->isValid to false in your code after doing the necessary checks that you want.

Be aware that the $event->feedData you are working on is an array representation of your feed data (converted from, XML, JSON or whatever). So you need to do your checks accordingly. At this point, Feed Me has not tried to match against potentially existing elements in Craft. Your example code basically assumes there's a field in the feed element with the name status with the value false. If that's not the case, you could do your checks on whatever you want, before a certain date, etc.

But if it is, something like this would be likely to work (again untested):

if($event->feedData['status'] == "false") {

    $event->isValid = false;
}

If you're looking to skip based on some Craft element, you'd either need to query for it (basically doing some custom matching), or use an event later in the process (I can help you out there too, but maybe it's easier in your case to skip it already here).


I need to update an existing URL I have inherited a Craft website and need to update an existing URL, it will open a PDF document, so I need to replace an updated PDF

I have very basic Craft knowledge so need assistance.  I have added a Screenshot below showing the inforamtion behind the link which I hope helps

You can replace a file directly in the control panel. Navigate to Assets, select the file you want to replace and then click the cog icon to select the “Replace file” action.


How can I set an entry title automatically, based on a related entry? If a booking channel contains two Entries fields (one related to a single User, one related to a single 'Event'), how can I get the booking entry title to be set automatically to the following syntax:

"Event Date - Username"

I've set up the entry to not show the title field, but my syntax is wrong. I'm using:

{{eventBooking.title}} - {{userBooking.username}}

but all I'm getting is "-", so it's obviously not recognising the fields. Is this possible?

I believe this is in regards to the Title Format feature, so just to be explicit in what I'm referring to, Craft Documentation calls this a Dynamic Entry Title.

The syntax you are looking for can take two forms:

1) Long form object syntax

Just as on the front end your entry is available via the {{ entry }} variable, within your Title pattern on the back end, the current entry is available via the {{ object }} variable.

So I believe the following should work, assuming you are using the actual field names:

{{ object.eventBooking.first().title }} - {{ object.userBooking.first().username }}

You need to use the first() method here because Relations fields return an array by default. Since you need to output your content directly, you need to make sure you are accessing the title and username properties via the Model they are associated with in that array.  If your fields are required, you can safely assume that the first item will exist in the array.

2) Short hand syntax

If what you are doing is simple, Craft gives you the option to make the syntax a bit easier and omit the object variable.  So the above could also be written with single curly braces as such:

{eventBooking.first().title} - {userBooking.first().username}


Allow a User Group to access plugin pages (without hasCpSection) I'm facing a problem which, on the surface, seems similar to this thread...

Like that other thread, I've found that a specific user group is unable to access my plugin's pages because the plugin is lacking a hasCpSection method. My plugin doesn't need a hasCpSection method, because there really isn't a "section" for people to access. Specifically, I don't need a link in the side nav, because my plugin doesn't have a main index page.

However, my plugin does have other pages. These other pages are only accessible via special links. Those special links appear on Entry edit pages, as a custom Fieldtype. These random pages are what I want my client to have access to.

And that's where I'm unable to use the solution provided in the related thread. Because when I link directly to a template, those pages are restricted by default. There's no way for me to "allow anonymous". I would have to give the user group full admin access (which is crazy), and then circle back and restrict permissions on the page.

Any suggestions? This kinda feels like a bug to me, or perhaps a feature request.

Register new user permissions to restrict access to those pages using the registerUserPermissions hook.
Then use registerCpRoutes to setup routes to a controller action which checks for required user permissions before rendering the templates.

Sorry if I’m missing something, but I don’t see how this has anything to do with the hasCpSection function.


Combined entries from sections across locales I'm merging entries from two separate sections across locales.
All going well but when I try to paginate the results I get the following error:

Recoverable error

Argument 1 passed to Craft\TemplateHelper::paginateCriteria() must be an instance of Craft\ElementCriteriaModel, array given,

The offending code as follows (simplified):

{% set pages = [] %}
{% set devNews = craft.entries.section('newsDevelopment').status(null).find() %}
{% set alumniNews = craft.entries.section('newsAlumni').status(null).locale('prior_alum').search('shareNewsAlumni:1').localeEnabled(false).find() %}
{% set pages = pages|merge(alumniNews) %}

{% paginate news as pages %}
    {% for article in news %}
        ...
    {% endfor %}
{% endpaginate %}

As I say, works fine/as expected without the paginate but as soon as I try to paginate I get the error.

Any thoughts on above appreciated.

The paginate tag requires a criteria model, which means you have to come up with your own pagination solution.

See an example here:
Paginate entries when I do not have a criteria model?


Entry URIs incorrect when using entriesService->saveEntry() I'm doing an import, and saving entries into a channel with saveEntry(), but the entry's URL gets saved in the wrong format.

The URL format for the channel is: news/{postDate.year}/{slug} and I'm saving the entry with the following code:

$title = utf8_encode($article['article_language_name']);
$description = utf8_encode($article['article_description']);
$text = utf8_encode($article['article_text']);
$date = new \DateTime($article['article_start'], new \DateTimeZone('Europe/Oslo'));

$entry = new EntryModel();
$entry->sectionId = $targetSectionId;
$entry->typeId = $targetEntryType;
$entry->authorId = $targetAuthorId;
$entry->postDate = $date;
$entry->enabled = true;

$entry->getContent()->title = $title;
$entry->setContentFromPost(array(
    'leadText' => $description,
    'bodyText' => $text
));

$success = craft()->entries->saveEntry($entry);

All the URIs lack the year param in them, but that does get included if I save the entry via the CP afterwards.

What am I doing wrong? The postDate seem to be in the correct format, but maybe I'm missing something?

Ok, so the answer was quite simple: I was using the PHP DateTime object instead of Crafts DateTime.

Removed the \ on this line:

$date = new \DateTime($article['article_start'], new \DateTimeZone('Europe/Oslo'));

and everything worked perfectly.


How can I do nested ordering? I want to put the index of section in order by two fields: featured and startDate. Basically, I want the featured entries to rise to the top of the index, and then within the featured posts I want them to be sorted by startDate field. Below the featured entries, I want the other entries to also be sorted by startDate.

I tried entries.order('featured desc').order('startDate desc') but, as I expected, it simply ordered by startDate because that method executed after ordering by featured.

Is there any way to achieve what I'm tring to do?

This should get you the desired results:

{% for entry in craft.entries.section('yoursection').order('startDate desc, featured desc') %}

    {# Entry Code #}

{% endfor %}

If for any reason that doesn't achieve exactly what it is you are looking for, you could always break it up into multiple loops, 1 for featured, and 1 for not featured. It's not as clean as the above solution but should also solve the issue:

This will use 2 loops, one for the featured and 1 for the not featured, assuming the 'featured' field is a lightswitch.

{% for entry in craft.entries.section('yoursection').search('featured:1').order('startDate desc') %}

    {# Entry Code #}

{% endfor %}

and

{% for entry in craft.entries.section('yoursection').search('featured:not 1').order('startDate desc') %}

    {# Entry Code #}

{% endfor %}


Can you override the default sendmail path in Sendmail transport config in Craft 3? Many shared hosting accounts require custom flags that are passed to sendmail in order for them to work properly.

Since Craft 3 uses Swiftmailer for its mailing library and Swiftmailer's default Sendmail command is /usr/sbin/sendmail -bs (https://github.com/swiftmailer/swiftmailer/blob/master/lib/classes/Swift/Transport/SendmailTransport.php#L30), is there a way to override that from Craft's config/app.php to set a custom sendmail command?

There are some examples of how to override the mailer component and transport settings in the official Craft docs here: https://docs.craftcms.com/v3/config/#mailer-component

For this particular sendmail example, you'd need to do something like this from config/app.php:

'components' => [
    'mailer' => function() {
        // Get the stored email settings
        $settings = Craft::$app->systemSettings->getEmailSettings();

        // Override the transport adapter class
        $settings->transportType = craft\mail\transportadapters\Sendmail::class;

        // Create a Mailer component config with these settings
        $config = craft\helpers\App::mailerConfig($settings);
        $config['transport']['command'] = '/usr/bin/sendmail -customflags';

        // Instantiate and return it
        return Craft::createObject($config);
    },
]


Is there a way to remove the admin panel logout timer? Having to log in again every few minutes while on a local development environment significantly slows your workflow.

The duration of the session can be extended via userSessionDuration in your Configuration

'userSessionDuration' => 7200


Twig code showing in browser I'm learning how to use Craft. I've set it up locally using MAMP (regular) on OS X Yosemite (10.10.5). Everything is working fine until I start getting into Twig templates. When I try viewing files that contain twig code in any browser, the browser shows the twig code as content (for example, I see{% block main %} and {# comments #} within the window). I'm thinking this is a MAMP issue.

However, as I understand it, Craft itself uses Twig. If that's the case, then it wouldn't be a MAMP issue, since then both the Craft admin site and my files wouldn't work. Any hints as to where the problem lies would be greatly appreciated. Thanks!

Update: Trying to access it through MAMP Pro to see if that makes a difference. Now I'm being blocked right after the root. Here's a pic of the error (result with localhost in the URL not the file path):

I don't know anything about Apache -- is it safe to display my entire httpd.conf code online to see if anyone knows it's a setting in that files that's causing the issue? I'm sorry -- this question/thread is all over the place.

Are you opening those templates directly in the browser? When you do this, you are bypassing Craft and the browser does not know what to do with the Craft tags or how to access the database and will show the tags instead of the contents.

Since you have got the CP working, all should be good though. If you go to the CP and click on your bold site name at the top left in the nav,  the default homepage (or yours) should get loaded. What you actually see there is the index.html loaded into the _layout.html and you should not get any twig template tags. If you go ahead now and add some made-up segment to the address in the address field of the browser /xyz e.g., you will see the 404.html loaded into _layout.html.

To see your templates like your visitors will see them, Craft needs to kick in. This will only happen, if you enter a pages complete url in the browser, not a template location on your disk. (If you opended the templates directly, your address will look somethin like file:///Applications/MAMP/htdocs… which will not work. Visible or not, your address should always begin with http:// …)

Have you still got the default news section in the install? You could add 2 or 3 dummy news in the CP, and then navigate to those news entries as described above. The template that gets used to display a single news is news/_entry.html but _entry.html will never be part of the url. It is used by Craft to fill in the contents and your urls will be somtheing like news/dummy-news1, news/dummy-news2. Hope that makes it a bit clearer?


How can I fire a controller action for a particular route or entry? So I have an entry that has some content displayed in a template.

However ahead of displaying that entry, I want a plugin's action to fire, which pulls some data in from a third party API that will display along with the entry content in the template.

The data from the plugin would need to be available in the template that gets loaded.

What's the best approach to do this?

Here's my routes.php file:

return array(

    'book' => array(
        'action' => 'micros/availability/search'
    )

);

And my plugin:

<?php
namespace Craft;

class Micros_AvailabilityController extends BaseController
{

    protected $allowAnonymous = true;

    public function actionSearch()
    {
        Craft::dd('Micros_AvailabilityController->actionSearch()');
    }
}

I have an Entry with a slug of 'book' and that loads a template from the templates directory, so what I'm seeing right now is that template, and I don't get the action method running at all.

What I want to do is do something in my action and attach the data to the request and return to whatever template the entry is using.

It's more clear to me now that I've seen the database and extra description from the ticket.

The issue is that you've got an entry that already has has the URI of book.

Normally the code you're trying to use would work, but in resolving a route Craft matches any entry/category requests (Step 4) before it matches any dynamic routes (Step 5).

When you're testing the action URL directly in the browser that works because it hits step 2.

One way to pull off what you're looking for is to give your plugin a template hook.  Then from the template that loads when book is hit, you can do something like:

{% if craft.request.getSegment(1) == 'book' %}
    {% hook "myAwesomeHook" %}
{% endif %}


Use Imager plugin with AssetTransforms defined in admin panel I'm trying to use the Imager plugin with some asset transforms that I've defined in the admin panel.  Passing the name of the transform is just tossing an error at me.  Is there a way to do this, or do I need to define the transforms inline?

You'll have to define your transforms inline - Imager doesn't support named (i.e. CP-/admin-defined) transforms.


How do I print a value from Craft/Twig into a Javascript function? I just want to print a value from Craft into a JavaScript function to filter a dashboard.

The function is this:

showOnly(filterName, values);

I tried this:

showOnly('Short Names','{{ entry.title }}');

But that did not work.  And yes, the filter does work If I hard wire the value that Craft/Twig should print.  But, I need it to match the title of the page as one navigates from entry to entry.

UPDATE

Here is the actual showOnly function in its entirety:

function showOnly(filterName, values) {
    // Think a single select filter.
    sheet = mainViz.getWorkbook().getActiveSheet();
    if(sheet.getSheetType() === 'worksheet') {
        sheet.applyFilterAsync(filterName, values, 'REPLACE');
    } else {
        // for dashboards
        worksheetArray = sheet.getWorksheets();
        for(var i = 0; i < worksheetArray.length; i++) {
            worksheetArray[i].applyFilterAsync(filterName, values, 'REPLACE');
        }
    }
};

That is the correct way of doing it but you need to be sure that entry is a variable and set to an entry model at that point.  And that you're in an appropriate part of your template in general for outputting the code.

E.g. this works for analytics for example, placed at the end of my main structure block.

{# ANALYTICS GOOGLE #}
{% set js %}

{% endset %}

{% includejs js %}


What's the configuration to enable Craft for free CloudFlare and Railgun? This is the host-installed version of CloudFlare/Railgun as offered very successfully at Arcustech.

The arrangement is different from Railgun offered with the $200/month CloudFlare Business plan. It is free, and it takes a different approach to configuring the connection between your site and Railgun's high-speed server.

The configuration needs to operate properly with Locale multilingual features, and with SSL coverage for Craft CP admin and Stripe e-commerce pages.

I'm going to answer this one, to share information on how I just did it. One issue will remain, but that will be raised in a separate question.

The first thing is to understand the URL layout which CloudFlare/Railgun will require. You or your hoster will create A records in DNS for all but one of these, each of them pointing to your server IP.

There's an order in which these records should be created, which your hoster will specify, in order to check all is well before aetting the CloudFlare service to be fully active for visitors to your site. So don't just go ahead from this list!

Your main site, which will remain un-accelerated, but is a necessary DNS reference, and fallback if you disconnect CloudFlare. We'll call that domain.com.
The access subdomain, where CloudFlare/Railgun retrieves content from your site in order to accelerate it. This will be cloudflare-source.domain.com, or similar if your hoster differs.
if you're going to need SSL (https) to protect your Craft CP admin, you'll need a non-CloudFlare url to allow this, unless you're using one of the non-free versions of CloudFlare which allow SSL. Let's call this secure.domain.com.
Notice that secure.domain.com on https/SSL can also be what you'd use to shelter e-commerce pages, but be very careful here. Unless you want to be required to go through a process of certifying PCI compliance, you'll want to use an actually self-safe e-commerce solution like Stripe.js, which handles customer and credit card data so that they are never sent to your server. The secure page set up here just adds security against mistakes, and helps build customer confidence by showing visibly that everything is protected by SSL.
Any other subdomains such as a staging server will need to be on the same domain DNS record set, and also controlled by your server's virtual hosting config to arrive at the proper html folders on your site.
Finally, and as mentioned, only after all the CloudFlare arrangements have been verified operating as your hoster show you to do, then a final DNS record will be added, by you or them depending on who's managing DNS. This will be a CNAME record aliasing www.domain.com, and it will point not to your site, but to the CloudFlare URL you'll be given, something like www.domain.com.xyz.cloudflare.net.

Ok. Notice that the CNAME alias is from www.domain.com. Your hoster will give you a set of prefix rules to go in your public Craft directory's .htaccess file, above the handling which calls Craft itself. If you have special rules there to cause automatic switching to SSL for the Craft CP, a small portion of those will need to go before the CloudFlare additions. I'll cover that in another question/answer on automatic SSL itself, updating an earlier post to one of the cookbooks, and as setup has slightly changed.

The result of the DNS and .htaccess additions is that your site will now always redirect visitors to www.domain.com even if they originally linked simply domain.com. As you can see, www.domain.com is aliased by the CNAME record to call CloudFlare rather than your site directly, and that's how the speed-up caching is applied.

Railgun will also operate on this URL once you turn it on from your CloudFlare control panel, the one which will have been set up for you by your hosting provider. You want to let them do that, as it is different and differently connected than one which would result from you signing up to CloudFlare independently, thus enabling your hoster's service.

Then you can see why the extra cloudflare-source DNS access is needed. Your main site will refer to www.domain.com, which comes from CloudFlare. CloudFlare must then get its picture of your site from somewhere else, and cloudflare-source.domain.com is that place.

Now that we have CloudFlare arranged via DNS and .htaccess, what do you need to do in Craft configuration to properly use it? As it turns out, not very much.

You need to refer Craft to the now-required www.domain.com wherever it needs reference to your site, rather than domain.com. In particular, the constant siteUrl needs to be set this way You can do that in the CP General configuration page, and/or as a definition in general.php.

Thus if you are not using languages (Locale on Craft Pro), in general.php you would set:

'siteUrl' => 'http://www.domain.com/',

while if you are using languages you would in general.php set the siteUrl array by the same principle, according to the languages on your site. This example is for English, Russian, and Swedish:

'siteUrl' => array(
    'en' => 'http://www.domain.com/en/',
    'ru' => 'http://www.domain.com/ru/',
    'sv' => 'http://www.domain.com/sv/',
),

Several such arrays can be used individually as ever within a multi-site configuration, covering staging servers and so forth if you use that method. With or without multisite, if you've set your staging server as its own subdomain, then that will automatically bypass CloudFlare/Railgun for staging, which is very likely what you'd prefer.

Lastly, if you are using Craft Pro languages (Locale), you'll need to copy the fully equipped main site .htaccess to each of the language folders on the html site, so that they will respond appropriately. Not an option, and one of those fun ways to go wrong with languages, which when set up properly, are on Craft very easy and practical to work with.

How much improvement do you gain, from setting this up?

It can be quite dramatic.

On initial Pingdom testing and a site of not quite medium complexity, I'm seeing >5x improvement monitored in the US: from 2.5 seconds to 0.3 seconds for full all-images page loads, that important first customer access to your site.

Going overseas, CloudFlare is making practical a European customer's site from a single server base at Arcustech in the US. The same ordinary first-load pages go from 3 seconds to under 0.5 seconds. A difficult page with video players on it goes from around 25 seconds to around 1.7 seconds complete, both of these in Amsterdam from Minneapolis servers. The delay on the slow page is due to the video player background loading of libraries, so the screen view comes up more rapidly, but you can see it would be unusable without CloudFlare.

You can see that the CloudFlare-amplified service is as if it was local in Amsterdam. Across Europe one can see via Pingdom that not all areas will be as fast, but with the distribution of CloudFlare edge  servers, all will be practical; 1-second pages say instead of half-second, and a little more for the video page, but by use of player-assisted 'poster' images it comes up visually much more quickly than it completes, so a few seconds will be fine there also.

These figures are assuming the caches are full at the edge servers. The very first access will be slower, if helped by CloudFlare's excellent connections, as always with a cache.

How much Railgun adds, for which we take this special configuration's effort, has to be complex. If you are running CNN-sized pages, it will measurably help a lot, as big boys and girls are using it, as well as other edge caches with similar (and very expensive) features. If you are running small pages, most of the time it will not be so visible. In between, in between.

However, I suspect Railgun is likely to speed up first-viewer-on-empty-edge-cache page speed also, due to its keepalive single connection and compressed, high-availability path. Similarly, it should help unexpectedly more than usual whenever there is network congestion and extended latency, which as anyone who uses or monitors them knows certainly happens a lot on transoceanic paths. As we note with the Netflix wars bringing it to visibility, it's not happening a little within North America itself. Edge caching and delta compression sending only in-page differences is clearly a way to insure and proceed, when it is free as in these Arcustech-type arrangements; at least I feel so for my present and future customers.


Get all craft.embeddedAssets I'm new to using craft cms and have been using this site to answer several questions. I decided I should give back. I have been using the Embedded Assets plugin but could not figure out the "for loop" code in a Matrix field to display links to all selected YouTube videos.

This is one part of a bigger switch case statement for a Craft Matrix field.

My block is called newFeatureVideo.
my field is called video.

{% case "newFeatureVideo" %}
  {% for items in block.video.all() %}
    {% set item = craft.embeddedAssets.get(items) %}

{{ item.title }}

  {% endfor %}


FeedMe + Google Maps plugin Address fields missing Just upgraded to GoogleMaps plugin (from SmartMap) and trying to replicate FeedMe feeds.
When I go to assign field -> feed element, I see

my regular entry field
I don't see the address sub fields, but rather just a singular address field.

I don't see the subfields as displayed here:
https://plugins.doublesecretagency.com/google-maps/guides/importing-addresses/#feed-me
Halp?

Good news! The two plugins are now fully compatible as of Feed Me v4.3.6.
Update to the latest version of Feed Me, and give it another shot!


Database: Syncing "craft_fields" table through SQL dumps not possible? I've been trying to simply sync an addition to a matrix field building block from my local dev server to the live environment database by doing a SQL dump of the "craft_fields" table. I now have the same entry appearing in the remote database, however in the CP fields setup the additional field is not showing up in that particular matrix field.

What am I doing wrong? Or in other words: How can I optimize the workflow without having to do everything twice, in each CP (dev/live), for each field added later in the project's process?

Manually adding fields in both CPs is very prone to errors …

You might want to develop a workflow where you have one database (usually live production or staging) where all changes are made, and then sync down the database/assets from there.

Adding this concept of which server is the "source of truth" will greatly simplify keeping things in sync.

Craft-Scripts are a collection of shell scripts that help you do just that. All of this is discussed in detail in the article Database & Asset Syncing Between Environments in Craft CMS


Order grouped results by dropdown order Following this topic, I have an additional question.

The results are not ordered by the order of the Dropdown Options.
How can I get this done?

Code:

{% set players = entry.myPlayersMatrix %}
{% set playersGrouped = players|group('myPositionDropdown.label') %}

{% for position, playersInPosition in playersGrouped %}

{{ position }}

    {% for player in playersInPosition %}
        {% set playerData = craft.entries.section('myPlayersChannel').relatedTo(player).first() %}

            {{ playerData.fullName }}
            {{ playerData.age }}
            ...

    {% endfor %}

{% endfor %}

You could wrap this in another for loop and put a condition on the inner fors,

something like

{% for option in myPositionDropdown %}

{{ option.value }}

  {% for position, playersInPosition in playersGrouped if position == option.value %}

    {% for player in playersInPosition %}
      {% set playerData = craft.entries.section('myPlayersChannel').relatedTo(player).first() %}

        {{ playerData.fullName }}
        {{ playerData.age }}
        ...

    {% endfor %}

  {% endfor %}

{% endfor %}

(untested code)

That sort of idea though, loop the dropdown in order and show the grouped results. Heck, you probably don't need to group them at all since you're filtering them out in each loop.

HTH


Saving to table field via plugin I'm dealing with the import plugin, processing a .csv file.
in the .csv there's a column with | separated values that shoud be inserted in a table field.
The entry are created correctly, also the table field ( just 1 column ) has the correct number of rows, but the content is empty ( $featureContent length is > 0 ).
Here's the code, what am I missing?

foreach ($fields as $handle => $value) {

   $value = explode('|', $value);
   $content[$handle] = array();

   foreach ( $value as $featureContent ) {
      $featuresRow = array( 'singleFeature' => $featureContent );
      array_push( $content[$handle], $featuresRow);
   }

 }

--- Edit ---

According to this response the table data is stored in Json format, so now I'm trying to create the table providing a json formatted string.
As this:

[
  {"col1":"very beautiful"},
  {"col1":"really beautiful"},
  {"col1":"astonishing beautiful"}

]

Still, this doesn't work for me. It doesn't even creates the 3 rows as the other approach.

The answer on the previous question is a little bit off - you do not want to use json_encode to save the field. Just use the actual array:

$tableValue = [
  [
    "col1": "Product #1",
    "col2": "5",
    "col3": "10",
    "col4": "15"
  ],
  [
    "col1": "Product #2",
    "col2": "7",
    "col3": "14",
    "col4": "21"
  ],
  [
    "col1": "Product #3",
    "col2": "7",
    "col3": "14",
    "col4": "21"
  ]
];

$entry->setContentFromPost(array(
  'tableField'=> $tableValue,
));

Note that 'col1', 'col2', etc, refer to locations in the table. The handle of the table column is not used.


Filter entries by other entry There's a section called locations and another called vacancies. In vacancies the admin can assign a location entry to a vacancy.

On the careers overview page we want to display selected vacancies block.vacancySelected.

In the template we loop through all locations and would like to display the number of vacancies per location.

{% set lparas = {
    section: 'locations'
    } %}
{% set locations = craft.entries(lparas) %}

{% if locations | length %}
   {% for location in locations %}
      {% set cEntries = block.vacancySelected.relatedTo(location) %}
      {% if cEntries| length %}
         {{ location.locationName }} ({{ cEntries | length }})
      {% endif %}
   {% endfor %}
{% endif %}

But for some reason it shows all locations and the total number of vacancies per locations. It seems to ignore that we only want to show the locations of the selected vacancies.

If I correctly understand your question, you want to show each location with at least one vacancy, and the number of vacancies for that location? I don't really get what block.vacancySelected is?

The way I would do this:

{# get all locations #}
{% set allLocations = craft.entries.section('locations').all() %}

{% for location in location %}
    {# get a vacancy count for this location #}
    {% set vacancyCountForLocation = craft.entries.section('vacancies').relatedTo({
        field: 'locationFieldHandle',
        targetElement: location,
    }).count() %}

    {% if vacancyCountForLocation %}
        {{ location.locationName }} ({{ vacancyCountForLocation }})
    {% endfor %}
{% endfor %}

To prevent loading all locations, even if they have no vacancies, you could also try (untested):

{# get all locations, but only if they have related vacancies #}
{% set allVacancies = craft.entries.section('vacancies').ids() %}
{% set allLocations = craft.entries.section('locations').relatedTo({
    field: 'locationFieldHandle',
    sourceElement: allVacancies,
}).all() %}

{% for location in location %}
    {# get a vacancy count for this location #}
    {% set vacancyCountForLocation = craft.entries.section('vacancies').relatedTo({
        field: 'locationFieldHandle',
        targetElement: location,
    }).count() %}

    {{ location.locationName }} ({{ vacancyCountForLocation }})
{% endfor %}


UnexpectedValueException after loading plugin I'm attempting my first Craft plugin and trying to update https://github.com/matthewattanasio/Craft-Url-Decoder-Twig-Extension for Craft 3 and followed the instructions in the docs for loading plugins which seemed to work in that the plugin appeared in the control panel, but I also got the following error:

  [UnexpectedValueException]
    Package cakephp/core's source key should be specified as {"type": ..., "url": ..., "reference": ...},
    {"type":"git","url":"https://github.com/cakephp/core.git","reference":null} given.

and now when I try to run any more composer commands I get the same error so I'm unable to do

composer remove package/name
composer require package/name

because I've made some changes to file names and need to update it.

The plugin is still showing in the CP but showing old information and when I try to install it, I get a server error.

The solution was to replace all references to "reference":null with  "reference":"" in /craft/vendor/composer/installed.json.


Craft 3 front end form file uploads not saving if filename exists? I have a front end save entry form which users can attach photos too, it all works fine unless a photo with the same filename is saved, in this instance the entry saves but the asset field is just left blank, can't find anything in the docs,

Any help or a point in the right direction appreciated!

<form id="addCompanyForm" method="post" enctype="multipart/form-data" accept-charset="UTF-8">
  {{ csrfInput() }}
  <input type="hidden" name="sectionId" value="7">
  <input type="hidden" name="enabled" value="0">
  <input type="hidden" name="action" value="entries/save-entry">

  <input id="title" type="text" name="title">
  <input id="companyLogo" type="file" name="fields[companyLogo]" accept=".png, .jpg">

  </form>

That's a bug. The Asset wasn't saved because it would not be validated due to conflicting filenames. Thankfully, it's fixed now.


Possible to set Forgotten Password path in config? Looking at the documentation here: https://docs.craftcms.com/v2/config-settings.html#users

I have set loginPath, invalidUserTokenPath and setPasswordPath. However, it appears that there isn't a config option for the forgotten password template.

It's also not mentioned as an option (unlike the other path options mentioned above) on this doc: https://docs.craftcms.com/v2/templating/forgot-password-form.html

EDIT: Forgot to add that I have got it working in the meantime by setting
{{ url('users/forgotten-password') }} in my login template.

Thanks.

I think that this is because Craft never needs to get there by itself.  It's a page you will always link to in one of your templates.  So in theory, you can simply link directly to your Forgotten password template, like you did already.


Error: File to import not found or unreadable: ../../../../../lib/craftcms-sass/mixins I have two Craft websites running locally and they both have broken css on the backend due to the error below. Every time I update it is temporarily fixed but after a few clicks or refreshes it's back again. I've checked the permissions but the problem seems to be the location of the file.

Error: File to import not found or unreadable: ../../../../../lib/craftcms-sass/mixins

When opening the dashboard.scss I can see the path is incorrect but I'm very unsure what the proper path should be, and whether I should manually change it.

Is this a known problem? I hope someone here can help me out!

Okay, so it turns out my file watcher (WebStorm) was the cause.
It compiled the dashboard.scss, so I simply changed the Scope to make sure it only compiled my own files.


Placing a Test Order (Craft Commerce) This is a really basic question but I have had trouble finding an answer, or documentation on it.

What is the best way to place a test order with a default Craft Commerce installation? I'm unable to get past the payment page while using the default 'dummy' payment method. I would like to test the order process, including confirmation page, email confirmation, order history, etc.

If you are using the example templates, the dummy gateway should be enough to submit an order. Are you displaying any error flash message from the payment controller?

{{ craft.session.getFlash('notice') }}

{{ craft.session.getFlash('error') }}

The dummy gateway also expects a credit card that ends in an even number in order return a success:

https://craftcommerce.com/docs/payment-gateways#dummy-gateway


Craft can't connect to db Hope you guys can help. I was working on my Craft site locally and now trying to upload it to the server but no matter what it says "Craft can’t connect to the database with the credentials in craft/config/db.php"

I have created the database in phpmyadmin along with the username and password.

Also my hosting provider is HostGator

This is what I have locally for the db.php.

return array(

    // The database server name or IP address. Usually this is 'localhost' or '127.0.0.1'.
    'server' => 'localhost',

    // The name of the database to select.
    'database' => 'simple-portfolio',

    // The database username to connect with.
     'user' => 'portfolio-rc',

    // The database password to connect with.
    'password' => 'r*****',

    // The prefix to use when naming tables. This can be no more than 5 characters.
    'tablePrefix' => 'craft',

);

And the server's db.php.

return array(

    // The database server name or IP address. Usually this is 'localhost' or '127.0.0.1'.
    'server' => 'localhost',

    // The name of the database to select.
    'database' => 'rchohan9_website',

    // The database username to connect with.
    'user' => 'rchohan9_portfol',

    // The database password to connect with.
    'password' => 'p************',

    // The prefix to use when naming tables. This can be no more than 5 characters.
    'tablePrefix' => 'craft',

);

Also the whole site is put in a folder so its not sitting in the root directory

Locally general.php looks like this

return array(
    'devMode' => true,
    'siteUrl' => array(
        'en' => 'http://localhost/portfolio',
    ),
    'environmentVariables' => array(
        'baseUrl'  => 'http://localhost/portfolio/',
    )
);

and on the server it's:

return array(
    'devMode' => true,
    'siteUrl' => array(
        'en' => 'http://rachnachohan.ca/website',
    ),
    'environmentVariables' => array(
        'baseUrl'  => 'http://rachnachohan.ca/website/',
    )
);

I am completely out of ideas of why its not able to connect to the db.

I know it's been a minute since you asked this question, but just in case - I encountered this same issue - the correct credentials but still not able to connect with the db.php config file. I changed "localhost" to "127.0.0.1" and that seemed to work, or at least get me to the next snag that I hit. Cheers!


Commerce: Payment does not get completed I am having trouble getting a payment completed (SaferPay, offsite gateway). After coming back from the payment provider I get redirected to the unchanged payment page again with the following error message: Payment Error: , the error code (?) is 0.

I have found this in the logs:

$_GET=array (
'commerceTransactionId' => '87'
'commerceTransactionHash' => 'f4dcff157345d68b54934791fe7b0522'
)
$_POST=array (
'DATA' => '<IDP MSGTYPE="PayConfirm" TOKEN="(unused)" VTVERIFY="(obsolete)" KEYID="1-0" ID="Oh7p4zbhSnWOUAzjGE5bAS4rSnAb" ACCOUNTID="401860-17795278" PROVIDERID="1395" PROVIDERNAME="PayPal Saferpay Test" PAYMENTMETHOD="16" ORDERID="2435" AMOUNT="3071" CURRENCY="EUR" IP="84.141.245.197" IPCOUNTRY="DE" />'
'SIGNATURE' => '3eec17d64cd2f4e9e57402e3efb1d91d79af35cf462f1f971ad2aa79ceda5e6814d7fb4d82cf2bfe044c791cbc38ea3007598d4d0ac6ba16db08e1abb2dc0b61'
)
$_SESSION=array (
'1c4d338641dbdf309e6ed655daae834eYii.CWebUser.flash.error' => 'Payment Error: '
'1c4d338641dbdf309e6ed655daae834eYii.CWebUser.flashcounters' =>
array (
'error' => 0
)
)

The QUERY_STRING cuts after the transaction hash:

'commerceTransactionId=87&commerceTransactionHash=f4dcff157345d68b54934791fe7b0522'

Strangeley enough it is working locally, where the log says the following:

$_GET=array (
'commerceTransactionId' => '56'
'commerceTransactionHash' => '2db11e4c56020b3adad7565478f2bc56'
'DATA' => '<IDP MSGTYPE="PayConfirm" TOKEN="(unused)" VTVERIFY="(obsolete)" KEYID="1-0" ID="GCzE6MbphEYrSAUYhlA9bnvY6Y7b" ACCOUNTID="401860-17795278" PROVIDERID="1395" PROVIDERNAME="PayPal Saferpay Test" PAYMENTMETHOD="16" ORDERID="2435" AMOUNT="20430" CURRENCY="EUR" IP="84.141.245.197" IPCOUNTRY="DE" />'
'SIGNATURE' => '0378583461a09e40efe22a39cc5c7ca4c3bbe4e7f89c041154b00bcd1b65604309d219bad395ee2fefabc8726e9afd2364b769baa08ac927317698a9ab795e8b'
)

Remotely it lives on a sub domain. What could be the problem?

Not an answer to the specific issue as such, but perhaps handy for future folks looking to debug issues in this area - you can dump the gateway request data with something like this in your business logic plugin:

(see hook docs here: https://craftcommerce.com/docs/hooks-reference#commerce_modifygatewayrequestdata)

    public function commerce_modifyGatewayRequestData($data,$type,$transaction)
{

        BusinessLogicPlugin::log("commerce_modifyGatewayRequestData");
        BusinessLogicPlugin::log("data");
        BusinessLogicPlugin::log($data);
        BusinessLogicPlugin::log("type");
        BusinessLogicPlugin::log($type);
        BusinessLogicPlugin::log("transaction");
        BusinessLogicPlugin::log($transaction);
 }

(assuming you have a log function in there that accepts strings and if not a string does a var_dump)

That at least gives you a full look at the data you're sending.

You can also modify the $data in there, and return $data at the end if you need to massage any of the data before submissin.  E.g. with eWay you should truncate some fields if they are too long or you will get errors...

E.g.

        if(isset($data['Customer']['Street1']))
        $data['Customer']['Street1'] = substr($data['Customer']['Street1'], 0, 49);

        ...etc

        return $data;

Similarly, after a transaction, you can log the response etc using this event: https://craftcommerce.com/docs/events-reference#commerce_transactions.onsavetransaction

(See what you can log at https://craftcommerce.com/docs/transaction-model)

craft()->on('commerce_transactions.onSaveTransaction', function ($event){

    $transaction = $event->params['transaction'];
    BusinessLogicPlugin::log($transaction->response);

});


How to use entry data? My question:
How can I use entry data in the craft backend?
An example for the use-case:

Author creates an entry for the section "Generate item". The entry has only a title/single word.
That created entry should be shown as a selectable item in a selection box.
Users can upload pictures and can select this newly created item in the upload form.
So pictures should get associated to the selected word.

I'm aware that I can use element queries in PHP or Twig.
My problem:
The use-case is simply that I need categories/entries should get created by authors (that have no access to real backend) and these should be relatable to another entry - but on the fly.
Thanks in advance for any kind of help!

You can't use entries from the control panel in other control panel fields without the use of a plugin. The only plugin I'm aware of that does this is https://plugins.craftcms.com/craft-dynamic-fields.
Depending on the use-case, which I don't totally understand, you might look at using an Entries or a Categories field too if you just want to relate an entry to another entry.