Break-up Element API Config into partials I'm working on a Vue SPA (single page application) for a client and my ElementAPI config file has grown to be quite large.  To make it easier to maintain I was looking for suggestions of how to have each endpoint in its own file.

Any feedback is appreciated!

I had sometime to review the documentation in more depth;
https://github.com/craftcms/element-api/tree/v1#transformer

An abbreviated example below. Note, I include all transformers in a /transformers directory within /config.

file - craft/config/elementapi.php

  return [
    'endpoints' => [
      // Home
      //
      'api/home' => function() {
        require craft()->path->getConfigPath().'transformers/home.php';
        return [
          'elementType' => ElementType::Entry,
          'criteria' => [
            'section' => 'homepage'
          ],
          'first' => true,
          'cache' => 'PT1M',
          'transformer' => new homeAPI(),
        ];
      },

      // About
      //
      'api/about' => function() {
        require craft()->path->getConfigPath().'transformers/about.php';
        return [
          'elementType' => ElementType::Entry,
          'criteria' => [
            'section' => 'about'
          ],
          'first' => true,
          'transformer' => new aboutAPI(),
        ];
      },

      // Remaining Endpoints...
      //
    ]
  ];
?>

file - craft/config/transformers/home.php

<?php
  namespace Craft;
  require craft()->path->getPluginsPath().'elementapi/vendor/autoload.php';
  use League\Fractal\TransformerAbstract;

  class homeAPI extends TransformerAbstract {
    public function transform(EntryModel $entry) {

      $bodyBlocks = [];
      foreach ($entry->homepageContent as $block) {
        switch ($block->type->handle) {
          case 'gallery':

            $bodyBlocks[] = [
              'gallery' => [
                'thumbnails' => $thumbnails
              ]
            ];
          break;

          // Remaining Fields...
          //
        }
      }

      return [
        'id' => (integer) $entry->id,
        'title' => $entry->title,
        'content' => $bodyBlocks,
      ];
    }
  }


Assets are not saved in dynamically generated folders I setup an Assets field called Images. My Default Upload Location is set as {parent.uri}/{slug}

My File System Path for that folder is img/

The directory structure that is generated is correct and in this format: img/artists/artist_name/category_name/project_name

But the images are being saved in the root img/ directory.

What am I missing?

I got the images to upload into correct folders by switching Image field to "Restrict uploads to a single folder" option. I also had to fix the File System Path in Settings>Assets>Asset Sources to the full file system path.


Include PHP file in plugin I currently am developing a plugin to gather XML restful data.
At one point in the file, I need to reference another PHP file, which will process various data.

As a test, the code in the included file should return output, as well (see code below).

I've tried to utilize the following code, but it doesn't work.  There is no error message, but again there is no data output.

Craft::import('plugins.aifeed.resources.Date_Formatting');

I've been looking here, but it wasn't clear to me how or if the 'included' file could be utilized.
Thanks for any leads.

Here is my code:

in Variables folder:
AiFeedVariable.php

<?php
namespace Craft;

class AiFeedVariable
{
        public function XmlVariable($optional = null)
    {
....
$strSampleDate = '2015-12-23';

Craft::import('plugins.aifeed.resources.Date_Formatting');

}
}

in Resources folder:
DateFormatting.php

<?php
namespace Craft;

class DateFormatting
{
$strDate_A=$strSampleDate;
echo '$strDate_A test...'.$strDate_A.'<br>';
}

You can simply load the file normally via php require once

require_once( __DIR__ . '/resources/DateFormatting.php');
$dataFormatter = new DateFormatting();

From your plugins init function or where ever you would like to call it.

Edit:

I hope your DateFormatting is not like you posted it because it has no functions. Btw Craft::import() has the advantage that you can import entire folders and it loads the class only to Yiis classmap which means that it is only loaded when you need it and not until then. If you want to use the file for sure, require once is the better way since Craft/Yii does the same in the very end.

Edit2:

Never mind, Yii uses include and not require_once, sry for the wrong info here. However... today the difference is not that big issue. Comparison include vs require_once


Dynamically load craft entries based on twig variable I am looking for something quite simple, but I still can't find a way to do it in twig syntax. So basically here is my code:

{% set upperlimit = 3 %}
    {% for entry in entry.getChildren() %}
        {% if loop.index0 < upperlimit %}
            <button type="button" class="btn btn-default ma-category-btn {% if loop.first %}first{% endif %} {% if loop.index == upperlimit %}last{% endif %}">{{ entry. title }} </button>
        {% endif %}
    {% endfor %}

<button type="button"  class="btn btn-default ma-more-category-btn">VIEW MORE CATEGORIES</button>

Basically when I click on the button "VIEW MORE CATEGORIES", it should load the next three children and create three more buttons like the ones in the for loop if there are enough children for that entry.

Is it possible to have this dynamic behaviour in craft and twig?

You can't use Twig for dynamic interactions on your site, as it is a server side language. Twig compiles to PHP code, which is then rendered and loaded to the DOM.

What you'd need is a script running in userland. The technique Stehen suggested is one way to do it, but you probably don't want your site's visitors to load all data right from the start, using the button simply to reveal already loaded "extra entries".

I'd say you should learn how to do AJAX loading with Javascript or jQuery. This is how you could properly address the desired behavior.

A way to make it work with your Craft template would be to split your entries list into multiple parts using the paginate tag. The first block would load right away and then with every click on that button each succeeding entry block is loaded into the DOM via Javascript.


Displaying Craft User Profile based on First and Last Name I don't want to ustilise the username or the ID of a user to get their profile info so I am using their first and last name. So far I can fetch the user based on first name:

{% set slug = 'first-last' %}
{% set firstNameSlug = slug|split('-')[0] %}
{% set lastNameSlug = slug|split('-')[1] %}

{% set user = craft.users.firstName(slug).first %}

How do I build on this code to fetch using the first name AND last name?

See: https://docs.craftcms.com/v3/dev/element-queries/user-queries.html#lastname

{% set slug = 'first-last'|split('-') %}
{% set firstNameSlug = slug[0] %}
{% set lastNameSlug = slug[1] %}

{% set user = craft.users.firstName(firstNameSlug).lastName(lastNameSlug).first %}

We only need to split once, so I spit the slug variable instead.

You were passing slug to the first name method, but you would want to pass firstNameSlug.

Alternately this can be written like this if you know the slug is correct:

{% set slug = 'first-last' %}
{% set user = craft.users.slug(slug).first %}

But you said you don't want to do that so I'll assume you know what you are doing.


Plugin Dev - Load third party library What is the preferred way of loading a third party library in a plugin? I'm trying to develop a plugin to extend SproutForms so that users get signed up to Campaign Monitor.

So far I've got an interface in the CP where users can provide their API keys and List ID's into the database, so now I just need to actually add the CM API library.

I know I can just require it, but I was wondering if there is a better way of doing this? Also where would I store the library, just in pluginname/lib/?

I second Brad on this, if there is a composer package, use that.

Whether you use a composer package or a library not found on packagist.org you'll still need to load it so that your plugin can make use of it.

Generally speaking, there are plenty of places where you can import/require third party libraries from but my recommendation would be to do so from the init() method in your main plugin class. As far as where to put it, I would go with one of these 5 acceptable directory names used most often in no particular order library, common, third, lib, or src. I'll use library in the following example.

Once you've downloaded/installed your third party library, your directory structure might look something like this...

plugin
    PluginClass.php
    controllers
    templates
    ...
    library
        campaignmonitor
    OR
    library
        vendor
            composer
            campaignmonitor
            ...

Given the outlined directory structure above, your init() method might look something like this...

// PluginClass.php
public function init()
{
    require_once './library/campaignmonitor/SomeClass.php';
    require_once './library/campaignmonitor/SomeOtherClass.php';
    ...
    // If using composer
    require_once './library/vendor/autoload.php';
}

I'd also like to point out that Craft::import() can theoretically import using glob as in Craft::import('plugins.pluginname.library.*) which is cool because those don't get required right away but lazy loaded when needed. However, this only works for class in the Craft namespace so you'll have to stick to a method described above: )

Hope that helps!


Accessing Commerce ‘Product Fields’ in events hooks I've added an Entries field called linkedCourseEntry to a Product (Product Type > Product Fields tab). In the Product itself I've assigned an entry.
I need to access linkedCourseEntry from one or more Events, but can’t work out how to do so.
For example when EVENT_POPULATE_LINE_ITEM is used:
Event::on(
    LineItems::class,
    LineItems::EVENT_POPULATE_LINE_ITEM,
    function(LineItemEvent $event) {

        $lineItem = $event->lineItem;
        $purchasable = $lineItem->getPurchasable();

        // Somehow access the 'linkedCourseEntry' data here... help!
    }
);

Can anyone point me in the right direction please?

I believe you're looking for something like:
$purchasable->product->yourEntriesFieldHandle->one()->title


Adding php.ini file to root crashes site My client's site is on name.com and in order to change the upload limit, I think i need to place a php.ini file in the web root. But Craft crashes when I add it. The site is fine when I remove it. Anyone know why?

They're uploading video and Craft is giving me the 8MB upload limit problem.

Changing the limit in the Craft config file isn't solving it.

Checkout a few different log files to see if they can help out.

craft/storage/logs/phperrors.log
If you're running apache, the apache log files
If you're running php on ngix or apache, the php log files


When using Settings -> Routes in the CMS with wildcard, routes.php does not work Not sure of this is intentional or a bug but, when we add a route using Settings -> Routes in the CMS, routes.php does not work. I guess maybe its due to us using a wildcard and this takes presedence over routes.php

The route we needed to add in the CMS was:

*/<teamid>

The reason we need a wildcard is because I don't want to hard code the page slug as this could be changed by a website administrator which would break functionality.

I added it in the CMS Routes because I can't find out how to add a wildcard in routes.php (perhaps worthy of another question as I would like that answer too!).

in the meantime I have to use routes.php and hard code the slug URLs as follows for each locale:

'contact-us/<teamid>'         => ['template' => 'pages/index'],
'cysylltu-â-ni/<teamid>'         => ['template' => 'pages/index'],

It would be great if I could either:
1) Use the CMS routes with this wildcard AND routes.php still works for all my others, or
2) Add a wildcard in routes.php (my preference)

Thanks

I don't know if it's great practice to do this but if you want a "wildcard", especially as your first segment, you should a) put it in your routes.php manually b) make it the last route (always) otherwise it will take precedence just as you said and the other routes won't work. Also, using regex in your named parameters is good practice, if you are sure that teamid> is always and only a number, you could do this <teamid:\d+> so that someone visiting contact-us/peanuts would get a 404.

As far as setting this catch all route you want, just use a named parameter again:

'<anything>/<teamid:\d+>'         => ['template' => 'pages/index'],

This would have your catch all effect and will allow you to fetch the first segment if you need to.

If you expect a certain format for this first segment, in your template by calling {{ anything }} you could do some sort of validation. Also you could use regular expression to narrow the possibilities down a bit... With this as is, 500shoes/54896 would return your index page...

Hope that helps :)


Many versions of the same structure of entries? If I had a structure representing the user guide of a product; is it possible to select a specific version of user guide entries from a URL?

http://www.example.com/myproduct/docs/v2.0/installation

Where the logic would be something like (pseudo-code):

craft.entries('myProductDocs').versionLowerOrEqual('2.0').slug('installation')

I see that Craft has some provision for versioning entries since you can select from the drop-down in the entry editor interface. Is there a way to tame this?

I don't know about searching by version ID natively — I don't think Craft has that capability out-of-the-box... but I can envision setting up such a user guide using a Matrix, where each Matrix block represents a revision of content: Each block would have a field denoting which version the content was written for, along with the content itself. By default, you'd display each entry's most recent content by sorting the blocks by version-update number, and selecting the single most recent block from the sorted set. However, you could also display the docs for a 'legacy' version by filtering out blocks where the version-update number is greater than the version of interest.


Is there a way to override the formatting template used when rendering a Freeform form? I have a form that can appear either in the regular body flow of a page, or in a sidebar-esque box. When rendering normally, I want it to use the formatting template selected in the backend, but when I render it in the sidebar box, I want it to use a different formatting template.

I know there's manual overrides for rendering everything exactly the way you want in a custom fashion, but I'm looking for something more like this:

{{ craft.freeform.form(entry.form.handle).render( { template: 'specialtyTemplateHandle' } ) }}

Is something like that possible?

We're using Freeform 3.6.2 Pro.

No, I don't think it's possible to pass a template file name to the render() method. The render() method is meant to use the template selected in the control panel. I don't think you can override that option.

From Freeform's documentation on the Forms Composer:

  Formatting Template
  Optional, if using the render() method, this essentially allows you to "attach" a formatting template to a form so that you don't need to include formatting inside the template(s) you place the form inside.

You can do something like pass a Freeform handle to another template via an include. If you have an entry with a Freeform field called sidebarForm it would look like this:

{% include "forms/sidebar-form" with {'formHandle': entry.sidebarForm } %}

Then the included template forms/sidebar-form could look something like this:

{% set form = formHandle is defined ? craft.freeform.form(formHandle) : null %}

{% if form %}

  {{ form.renderTag() }}

    manually iterate through fields...

  {{ form.renderClosingTag }}

{% endif %}

You can use Freeform's Formatting Template Examples as a starting place, or install their Demo Templates.


Errors after Upgrading from 3.0.35 > 3.041 I ran the updater from the Admin (local install.)
After a few minutes, the update failed.

Now when I try to load the site:

Warning: require(C:\Users\rickn\Documents\Craft\Projects\Untye/vendor/craftcms/cms/bootstrap/web.php): failed to open stream: No such file or directory in C:\Users\rickn\Documents\Craft\Projects\Untye\wwwroot\index.php on line 20

Fatal error: require(): Failed opening required 'C:\Users\rickn\Documents\Craft\Projects\Untye/vendor/craftcms/cms/bootstrap/web.php' (include_path='.;C:\php\pear') in C:\Users\rickn\Documents\Craft\Projects\Untye\wwwroot\index.php on line 20

There is no "vendor/craftcms/cms" folder

Is there a way to manually update an existing install? I don't see that option in v3 update instructions.

The easiest way is to make sure you have Composer installed.

Then you can go to your project's root and run composer update to pull in a fresh set of dependencies.


Structure a site with multiple locations with categories, structure or "multisite"? I'm proposing to use Craft for a company that runs multiple golf courses. Along with some general pages for the company as a whole, each location (course) is to have it's own microsite, for want of a better phrase. At the moment each location will have the same pages (but that could change in the future), along with a news section.

I think I can achieve this with a combination of categories and structures, but I'd be keen to know if anyone has any other ideas. (Possibly "multisite" with locals?)

My thoughts are:

Homepage - Single
Global About - Single
Global Golf Pros - Channel
Locations - Structure with individual entry types for each sub page
Global Contact Us - Single
News (there's no requirement for this to be global at the moment, but creating multiple news channels seems a little painful) - Channel (with category filed to scope to each location)

Within the Location's channel I can then use relationships for each location's Golf Pros (from the Global Golf Pros channel) and list news articles via twig craft.entries.section('news').categories('location-x') and a slightly elongated Entry URL Format "locations/{location.first.slug}/news/{slug}"

Sometimes a picture is worth a 1,000 words, so here goes.

I feel a little like I'm mixing the use of categories and structures though.

Any thought would be much appreciated!

Thanks in advance,

Tom

Another idea (since that's what you asked for) might be to leverage Relationships more than Entry Types.

I find that those administering the content have a better time with relationships than Entry Types.

Given that your

e.g. if Golf Pros' was a Structure (instead), which contained a required field called 'Related Location' your content admin person could logically click Entries > New Entry > Golf Pro

One area this could really help would be News. If a News article (Entry) contained the same 'Related Location' field, I think you'd have a better time templating and also provide a more logical publishing experience for your client.

The same could apply to the other Entry Types you have beneath your Locations; About, How to find us, etc.

As I said - it's only another approach - happy to discuss, Tom.

Matt


Import entries from more than one file I am developing a property listing website that imports properties from XML files (i.e there is one XML file for each property). Is there any way that we can do an import from more than one file using FeedMe plugin?

There is no way out-of-the-box so your only options would be to either create a module that passes multiple XML files into feed me using the direct feed url or to create a script/use software that merges all the files into one.


Asset Volume using Environment Variable on File System Path as literal string on upload I have a volume called "Website" with a File System Path that uses an environment variable, $ASSET_ADHOC_PATH. The variable has been setup in my .env file as follows:

ASSET_ADHOC_PATH="/home/theadhoc/craftcms/web/assets/theadhocracy"

The Volume has the following in the File System Path input:

$ASSET_ADHOC_PATH/website

That should resolve to my actual folder location, but when I upload a file it just creates a folder at:

/home/theadhoc/craftcms/web/$ASSET_ADHOC_PATH/website

If I get rid of the environment variable and use the literal value then it works fine (which is what I'm doing for now) but I'd like to get to the bottom of why this isn't working as I would expect.

EDIT: Just in case this helps, I've discovered I have the same issue when using (different) environment variables in the Base URL field too. Am I missing a step in setting up env vars? Do I need to add them to general.php or something as well? They seem to resolve without issue in the dropdown list, which accurately displays the variable contents.

If you use environment variables, you have to be aware that you can't add anything to it in your fields. What this means is that $ASSET_ADHOC_PATH/website in your CP will not be parsed. If you use environment variables, the only thing you should have in the field is the variable, nothing else.

To do what you are trying to do, you might want to consider Aliases. These are great for the Control Panel because you can add to them so @aliasName/website will be parsed
and work the way you expect.

So in your case (and to get you going) with this ASSET_ADHOC_PATH variable set in your .env file, add the below in your config/general.php:

'aliases' => [
    '@assetAdHocPath' => getenv('ASSET_ADHOC_PATH')
],

Then in your volume settings use @assetAdHocPath/website and this should now work for you.

For the second part of the question, I'm guessing you may be trying to access an ENV in your template in which case you would use {{ getenv('ASSET_ADHOC_PATH') }} OR if you go the aliases way, {{ alias('@assetAdHocPath') }}.


Sales that select both Product Types and Specific Products in the Conditions Is it correct to assume that if I set up a Sale with some Specific Products in the Condition, it will not have any effect to also select Product Types in the Conditions of that sale?

i.e. If I select both Product Types and Specific Products, does the sale apply to all the products in the selected types, and also to the selected specific products, or (my current understanding of the "correct behavior") would that sale apply to only the selected specific products?

A blank selection of products or product types will match all products.

Both 'product type' and 'product' conditions need to match for the sale to match the product.

If you selected product type A and a single product from product type B in your conditions, then the sale would not apply to the single product from type B even if added to the cart.

Therefore the condition could be thought of as an AND, meaning that all conditions need to match for the sale to apply.

Let me know if you need further clarification.


Permissions when crossing over from Windows to Mac I'm trying to work locally on a Mac installation of Craft but keep getting permissions errors with Storage, and so on. I don't get these errors when working locally on Windows using these same files (synced using Dropbox).

Is there a way to fix this without manually changing every file? I've changed the permissions for Storage and Runtime but am now getting Unable to create a cache directory. Even if there is a fix, will I need to repeat it for each project I create on Windows and later work on using the Mac?

Cheers,
Clive

I've got a nearly identical setup... a Windows 8.1 box using IIS and an OSX laptop using MAMP with Craft installs that are sync'd with Dropbox between them.

If I recall correctly, the only thing I did was give "Everyone" full recursive access to things like craft/storage on Windows and chmod -R 777 craft/storage on the OSX box.

Haven't ran into any permission issues.

I will warn you not to use symlinks in that setup, however, as Dropbox doesn't know how to resolve those cross platform.


Plugin Store does not load I did a fresh craft 3 installation in a local enviroment, but the plugin store does not load, telling me to check back later.

It was a problem on our side but we just pushed a fix. If you try again, you should be able to get on now.


Access optimizedTitle field within Twig template I'm trying to access the value set for my optimized title within Sprout SEO. I've had a read through this page: https://sprout.barrelstrengthdesign.com/craft-plugins/seo/docs/advanced-customization/custom-metadata-variable - but have had no luck.

Why I want to do this is because I'm loading my pages via AJAX and need to set the title once the content is loaded. I've tried various iterations of {{ entry.metadata.metadata.optimizedTitle }} but to no avail.

Alternately, do you know how to set the metadata to update upon each AJAX page load?

So to update this question incase someone happens to stumble across it.

With Sprout SEO you need to enable the Enable custom metadata variable option under 'Advanced' in the settings menu.

From there I set a twig variable with the value of my metadata title, in this case {%- set metaTitle = entry.metadata.title -%} and attach it to my AJAX wrapper element with something like data-title="{{ metaTitle }}".

Now when I load each page via javascript I just do a little something like this document.title = $('<div />').append(html).children('.js-ajax-wrapper').data('title'); once the content is loaded in and my page title is updated.


How can I pull my Username into the transformer of the ElementAPI plugin? The username that is entered in URL. I need to pass this data to my transformer as well since I have an EntryModel combined with a Matrix Field.

My problem is that I have a matrix field where there are multiple matrix blocks. I need to query them based on the user field.

This is added on to my original question: How do I query data using the Element API Plugin based on a custom field?

I don't know if there is another criteria setting that I could set so that the matrix would only grab the data for the requested user.

My only other idea was to loop through the matrix blocks and check to see if the username requested was equal to the matrix blocks username field. If it is -- then grab the data that I need and set that in a variable to output in the JSON.

However, I can't do this unless I can figure out how to get the username inside the 'transformer'.

Thanks in advance for all the help. I am learning a lot about this plugin and it is an excellent addition to CraftCMS.

I was able to pass the $username data to the transformer. By doing this:

'transformer' => function(EntryModel $entry) use ($username)


How do I change the /web directory? I'm extremely new to Craft CMS - I'm trying to install it on to a Cpanel as a test, upon downloading the CMS is gives you all the folders for craft, and then a separate /web folder.

If you move the contents of the /web folder outside of this, it causes an error. I've also tried moving the craft installation up one level, and then taking the contents of the /web folder out, but this also errors. am I missing something extremely obvious?

It's currently set up as a sub domain:

http://ea.cranberrywp.co.uk/web/

I'm looking to make it like this:

http://ea.cranberrywp.co.uk/

But as you can see that takes me to just the directory.

Sorry for the silly question!

you should point your domain to the /web folder and not to the craft main folder.


How to access Plugin Variable in Plugin? I want to access a variable created in Plugin itself. In Craft 2, it could be simply done by craft()->pluginName->getVar() but I couldn't find a way in Craft 3. I have tried Craft::$app->pluginName->getVar() but that throws an error.

You can access your plugin via

Plugin::getInstance()

You can then access its components defined by setComponents

Plugin::getInstance()->componentName

Or

Plugin::getInstance()->get('componentName')

If you just want to get properties of your main plugin class it's the same way as above. Not sure what you mean exactly by Plugin Variable


Do I need a plugin to load entries via AJAX? I want to load some entries via AJAX. I have a page that normally shows all entries of a specific type with user-selectable filters. I want to load filtered entries via AJAX.

Do I need to create a plugin to do this? If so, how can I use the Craft object in my JavaScript code to call Craft.ajaxActionRequest or Craft.postActionRequest?

There is a new RESTful plugin which might be what you need: Rest-Easy from Wes Rice.
But you could also make use of Twig's extends functionality:

_ajax.html:

{% block ajax %}
    { success: false }
{% endblock %}

entry.html:

{% extends craft.request.isAjax ? "_ajax" : "_main" %}

{% block ajax %}
    { success: true }
{% endblock %}

{% block normal %}

Normal entry

{% endblock %}

If you request entry.html via ajax, the template will extend _ajax.html instead of _main.html, and show your json data. In this example _main.html would be your normal layout-template.

Note: Don't forget to set the XMLHttpRequest in your ajax call.


Best Way to Build a Product Selector I have a channel on my site which holds the products and services available.
Each has various categories to narrow it down. I want to build a product selector and not sure the best method to go about it.
Concept is in image:

The first 3 questions are filters by categories which apply to each product/service. The Q4 is a price which each product/service has.

I already have a page set up with a custom route which filters the products based on the categories e.g:

/products-services/inks/sales-marketing/tiles  which is
/(to load template)/category/category/category

And that currently filters the products as required.

What is my best way to build the product selector? I'm guessing it is to build a url somehow and link to the above route I have already set up?
Could it be done with a structure with a sub level for each question?

If I understand correctly, it looks like you really only have 2 branches to your tree (products and services). Everything else applies to all products or all services respectively and is one-to-one (except for budget). Instead of using categories, I would probably opt for using Entry Type to determine whether it's a product or service, and dropdown and/or checkbox fields to determine the product/service attributes, which you can then use to search for products/services directly using an ElementCriteriaModel.

Channel => productsServices
    Entry Type => product
        Field => testingType (dropdown)
        Field => surfaceType (dropdown)
    Entry Type => service
        Field => reportingLevel (dropdown)
        Field => isoCertification (checkbox)
        Field => price

In your template, you can use javascript to display the correct form questions (based on the answer to the first question) using .on('change', function(event){..}). Select field options can be set dynamically from the field options. Budget options can perhaps be stored in a separate field in a global set ('budgetOptions') for example.

Who will test your self-cleaning surface?
<select name="productServiceType">
    <option value="product">I'll test it myself</option>
    <option value="service">I want the experts</option>
</select>

    What is the reason for your testing?
    <select name="testingType">...</select>
    What surface type will you be testing?
    <select name="surfaceType">...</select>

    What level of reporting do you require?
    <select name="reportingLevel">...</select>
    Do you require ISO certification?
    <select name="isoCertification">...</select>
    What is your budget?
    <select name="budget">...</select>

You can then submit the form to your productServices template, retrieve the attributes and find the associated products/services.

{# set default params #}
{% set params = {
    section: 'productsServices',
    limit: null
} %}

{# determine productService Type #}
{% set type = craft.request.getParam('productServiceType') %}

{# set product params #}
{% if type == "product" %}
    {% set testingTypeParam = craft.request.getParam('testingType') %}
    {% set surfaceTypeParam = craft.request.getParam('surfaceType') %}
    {% set params = params|merge([
        testingType: testingTypeParam,
        surfaceType: surfaceTypeParam
    ]) %}
{% endif %}

{# set service params #}
{% if type == "service" %}
    {% set reportingLevelParam = craft.request.getParam('reportingLevel') %}
    {% set isoCertificationParam = craft.request.getParam('isoCertification') %}
    {% set budgetParam = craft.request.getParam('budget') %}
    {% set params = params|merge( [
        reportingLevel: reportingLevelParam,
        isoCertification: isoCertificationParam
        price: '>= ' ~ budgetParam
    ]) %}
{% endif %}

{# retrieve entries #}
{% set entries = craft.entries(params) %}
{% for entry in entries %}
    {{ title }}
    ...
{% endfor %}

Not tested, but should be close.


Make entry in nav not clickable and reroute I have an entry that acts as a parent to several children pages. Trying to make so that particular parent isn't clickable AND reroutes to homepage if address url is accessed.

Not sure if I can work something into existing nav code or if this needs to be done somewhere else, but here's the code, nonetheless. Thanks in advance.

    {% set pages = craft.entries.section('page') %}
    {% nav page in pages %}

            {{ page.getLink() }}
            {% ifchildren %}

                    {% children %}

            {% endifchildren %}

    {% endnav %}

You can use the level method to determine which iteration of the nav you are on and change the behavior:

    {% set pages = craft.entries.section('page') %}
    {% nav page in pages %}

            {% if page.level == 1 %}
                {{ page.title }}
            {% else %}
                {{ page.getLink() }}
            {% endif %}
            {% ifchildren %}

                    {% children %}

            {% endifchildren %}

    {% endnav %}

of if it's only one particular entry, then you can create a conditional to check for that entry (using slug, id, title, or any other attribute or field value).

    {% set pages = craft.entries.section('page') %}
    {% nav page in pages %}

            {% if page.slug == "myPage" %}
                {{ page.title }}
            {% else %}
                {{ page.getLink() }}
            {% endif %}
            {% ifchildren %}

                    {% children %}

            {% endifchildren %}

    {% endnav %}

If the url is accessed directly you can add a redirect to the template.

{% if entry.level == 1 %}
    {% redirect siteUrl %}
{% endif %}


Why would one environment use "+" instead of "%20" for spaces when using url_encode filter? I just uploaded some templates to the server and discovered that some of my url encoded strings are being output with a "+" for spaces instead of the "%20" that is desired. It is fine in my local environment. Any ideas?

According to the twig encode_url documentation url_encode now uses php's rawurlencode by default:

  Internally, Twig uses the PHP urlencode (or rawurlencode if you pass true as the first parameter) or the http_build_query function. Note that as of Twig 1.16.0, urlencode always uses rawurlencode (the raw argument was removed.)

I have also tried passing 'true' as the first parameter just in case. No luck.

It looks like the twig url_encode filter uses the php function http_build_query if parameters are passed to it as an array. i.e. {'key':'value', 'key':'value'}|url_encode. Otherwise it uses rawurlencode.

http_build_query was modified in php 5.4 to include a new property enc_type, that allowed you to specify that it use PHP_QUERY_RFC3986encoding (which is also what rawurlencode uses).

The url_encode filter is defined in craft/app/vendor/twig/twig/lib/Twig/Extension/Core.php on line 596, and contains a clause to make it backwards compatible with php 5.3, but you obviously will loose the encoding type.

Options are: upgrade php to 5.4+; do not pass params as an array to the url_encode filter; or do a string replace on the encoded string.


Performing Image Transformations Locally Is there any reason why image transformations might not be working locally? I just get a bunch of these "http://site.dev/cpresources/transforms/7 404 (Not Found)" as error messages. The image directory has the correct permissions...

It is very likely that your "File System Path" on the asset source is unsuitable for a local environment.

You can set the fileSystemPath in your config like this:

'environmentVariables' => array(
    'fileSystemPath' => '../../public'
)

Then you can change your asset source settings to something like the following:


How to properly change / add to CP HTML I'm making a change to the CP so that clicking an asset thumbnail from the asset preview HUD will open the asset in a new tab. Specifically, I'm changing line 1685 of craftcms/cms/src/elements/Asset.php to this:

url . '" target="_blank" style="width:100%;height:100%;position:absolute;">';
This achieves what I want, but it's obviously not the right way to do it. My question is, what is the right way? Can I do this with a module as opposed to a full plugin?

The only feasible way of doing this without it being overwritten in each Craft update is by manipulating the elements using JavaScript. You can of course do this using your own module or plugin, but an easier approach would be to use the Control Panel JS plugin, which was created specifically to allow you to add JavaScript in the control panel.


Smart Map InfoBubble 'pointer' position I am having issues with the Smart Map infoBubble pointer position...

As you see the shadow is positioned correctly, but the white overlay triangle is too low down. Or the other way of thinking about it would be that the white overlay triangle is correct and the rest is too high. However, I think the problem can best be described as the former, that the white triangle is too low, knowing that the marker it is attached to is hidden away just showing behind the white triangle.

After inspecting this in Chrome, I cannot see the element / pseudo-element that generates this pointer visual... so cannot debug. Can anybody offer any assistance on how to fix this anomaly?

Thanks in advance,

Adam.

I'm going to guess that there is some sort of CSS or JS conflict which is causing this peculiar behavior. Smart Map must be bumping up against some other styling on the page.

Check through your existing CSS/JS to see if you can find the source of the conflict.


Craft with Redis session handling We've recently set up a Redis cluster to handle our PHP sessions since we use a load balancer to direct traffic into different craft instances.

We're seeing issues with redis when making back to back PHP session calls (using craft wrapper) very quickly. If we update a variable in the httpSession and then try to update it/get it very quickly it isn't updating. If we wait to access it then it is updated correctly.

How it's set up:
We modified the Apache2 php.ini to update the session handler to redis and the save path to our redis cluster (bypassing doing this via Craft). So Craft still uses its' default session handling but when it makes the request to save the session it gets redirected by apache to our redis.

Is it more beneficial to tie this to Craft by updating the General.php with the session override options? Will we see faster/better session handling? Is there a session lock happening in craft? Is Craft opening/closing the session after each httpSessionService call?

I can't say for certain if you would see faster session handling if you added the overridePhpSessionLocation config key, but have you added the appId and validationKey configuration keys? I was recently having issues in my load balanced environments because these keys were not set.


Craft 3: .find() deprecated but .all() fails? .find has been deprecated and we are told to use .all() instead. This seems to work for cases that don't have Eager Loading going on, but fails when eager loading is tried.

My working Craft 2 code might be:

{% set mixedContent = entry.mixedContent.find({
    with: [
        'singleImage:image',
        'imageGallery:images',
        'download:file',
        'relatedItems:relatedItems'
    ]
}) %}

Simply transposing ".find" with ".all" results in the following error:

Error: Call to a member function getQueryBuilder() on array

Switching the syntax I tried:

{% set mixedContent = entry.mixedContent({
    with: [
        'singleImage:image',
        'imageGallery:images',
        'download:file',
        'relatedItems:relatedItems'
    ]
}).all() %}

But got this error:

Calling unknown method: craft\elements\Entry::mixedContent()

What am I doing wrong?

Assuming mixedContent is a Matrix or relational field, the correct syntax would be:

{% set mixedContent = entry.mixedContent.with([
    'singleImage:image',
    'imageGallery:images',
    'download:file',
    'relatedItems:relatedItems'
]).all() %}


Plugins - Element Criteria Model. Can I return only entries with a updated date in the last 7 days? My plugin function is ignoring the dateUpdated criteria. Any clue as to why? I'm guessing it's syntax, but I cannot find any examples online as to how to format correctly. I can make this work in a template just fine. I'm new to plugins and PHP. Thanks!

$criteria = craft()->elements->getCriteria(ElementType::Entry);
    $criteria->section = 'guide';
    $criteria->order = 'postDate desc';
    $criteria->dateUpdated  > '("now"|date_modify("-7 days"))';
    $entries = $criteria->find();

    if ($entries) {
        //Do that thing with my code
    }

I'm not sure if there's some other Craft helpers / static variables that you could use, but this technique works. Create a DateTime object without the param set to get the current time, modify it and format it for use in the query like so:

$date = new DateTime();
$date->modify('-7 days');

// Format datetime for use in query
$timezone = new \DateTimeZone(DateTime::UTC);
$date = $date->format(DateTime::MYSQL_DATETIME, $timezone);

$criteria->dateUpdated = '> '.$date;


How can I force a slug to update on save I'm using the auto generate entry titles from custom fields option, eg

{eventVenue}-{seriesName}-{eventDate}

But sometimes the eventVenue isn't known at the time of creating the entry, so you can end up with a slug of tba-winter-2017-04-15. But when they later update the eventVenue the slug is not right. It's not very easy to explain to users that they can/should change the slug and for them to remember to do so.

I fully understand the thinking that in many cases the slug shouldn't change due to existing links that may exist and will now break, but is there a way to override the default?

In ExpressionEngine I used an addon, "Title Master" that had the option to update url on edit or not.

You could write a simple plugin that listened to the onSaveEntry and perform whatever custom business logic you require for slugs.

Don't re-save that entry going through craft()->entries->saveEntry(), though, or else you'll create an infinite loop by firing the onSaveEntry event again.

You could either call craft()->elements->saveElement() directly or use use QueryBuilder to directly update the database with the slug.


How do I hide tags in a category that have no entries? Entries can have one of two categories and one tag.
(People = entries | program = categories | year = tag)

On the pages I'd like to display entries related to the category and grouped by tag. However, I don't want the tag to display if there are no entries with that tag and in that category.

The following code works, but it displays empty tags that I'd like hidden.

{% set entryIds = craft.entries.section('fellows').ids() %}
{% set tags = craft.tags.relatedTo({ sourceElement: entryIds }).groupId(2).find() | reverse %}
   {% for tag in tags %}
      <h3>{{ tag.slug }} {{ category.title }}</h3>
          {% for entry in craft.entries({
                            relatedTo: [
                              'and',
                              { targetElement: category },
                              { targetElement: tag },
                              ],
                              limit: (null),
                              }) %}
           {% include '_entryblock.twig' %}
           {% endfor %}
    {% endfor %}

This currently displays the following — but I don't want it to display 2018 in Program A or 2017 in Program B since neither of those have entries.

Program A:

/program-a (category)
  |__2018 (tag)
  |__2017
       |__Bono (entry)
       |__The Edge
  |__2016
       |__Ringo
       |__Paul

Program B:

/program-b
  |__2018
       |__Chris Martin
       |__Jonny Buckland
  |__2017
  |__2016
       |__Florence
       |__The Machine

Here's a good tutorial on how to achieve this: https://straightupcraft.com/articles/how-do-i-only-display-a-list-of-categories-that-have-entries-and-hide-empty-categories


Display matrix block which share the same date field value I think a better way to achieve this would be with Supertable, but for now I'm wondering if there is a way to group the example output

W/C: 27 Aug 2018 {{ block.week }}

1.5 {{ block.totalTime }}

W/C: 27 Aug 2018 {{ block.week }}

2.5 {{ block.totalTime }}

W/C: 27 Aug 2018 {{ block.week }}

3 {{ block.totalTime }}

instead like

W/C: 27 Aug 2018

1.5

2.5

3

so values from the 'number' field {{ block.totalTime }}
which share the same value from the 'date' field {{ block.week }}
are somehow grouped together?

from the matrix fields in use below:

     {% for block in entry.timeSheet %}

        {% if block.totalTime | length %}

        W/C: {{ block.week|date('j M Y') }}

        {{ block.totalTime }}
        {% endif %}{{ not loop.last ? '
' }}

     {% endfor %}

I think what you're saying is that you only want to output the heading once it's different from the previous heading. So if you have two blocks with the same week, we only show it once.

You can set a variable of week and check that the current block's week (which I've set as tempWeek to keep code cleaner) is the same. If it isn't the same, it means we've changed week so display the title and then set week to be this new week.

{% set week = "" %}
{% for block in entry.timeSheet %}
    {% set tempWeek = block.week|date('j M Y') %}
    {% if tempWeek!=week %}
        W/C: {{ block.week|date('j M Y') }}

        {% set week = tempWeek %}
    {% endif %}
    {% if block.totalTime | length %}
        {{ block.totalTime }}

    {% endif %}
    {{ not loop.last ? '
' }}
{% endfor %}


Freeform - get option label & value on submissions page On the form I'm building, I've got a question with radio buttons. And the answers have custom values. e.g.

Q: What is your favorite color?

red (value: 10)
blue (value: 20)
yellow (value: 30)

On my submissions page, I have the following code

{% for field in submission.fieldMetadata %}

        {{ field.label }}/b>:

        {% set fieldValue = attribute(submission, field.handle).value %}
        {% if fieldValue is iterable %}

            {% for value in FieldValue %}

{{ value }}

            {% endfor %}

        {% else %}
        {{ fieldValue }}
        {% endif %}

{% endfor %}

And this returns:

What is your favorite color: 10

I'm using the values to do some funny math - so it's necessary (but unimportant to the issue at hand).

How to do I get the value "red" to show, instead of the 10?

attribute(submission, field.handle).value - shows the selected option's value (10)
attribute(submission, field.handle).label - shows the question (What is your favorite Color?)
attribute(submission, field.handle).handle - shows the question handle (whatIsYourFavoriteColor)

There should be another function to get the option's value, but I can't find what it is.

The code above is correct, but it turns out there was an actual bug in the code if you had a number as the option value.

This affects Freeform 1.5.1 and earlier. The next version (1.5.2) of Freeform will include a fix for this. If anyone needs a patched copy of Freeform before 1.5.2 is available, just contact us via our support form. :)


Eager load a list of entries, then only the first asset, from the first block type I would like to eager load:

A list of entries
Within the entries loop, the first image, from the first of a block type on a matrix field.

Loading the entries like this

{% set entries = craft.entries({
  sectionId: 12,
  with: [
    'pageContent.text:text',
    ['pageContent.images:images', {
      withTransforms: [{
        width: 100,
        height: 100
      }]
    }]
  ]
}) %}

Loading the images:

Currently, I can only seem to load an image like this:

{% for block in entry.pageContent %}
  {% if block.type == 'images' %}
    {% if img is not defined %}
      {% set img = block.images[0] ?? null %}

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

I cannot seems to filter the query to the matrix down like you can when getting a matrix normally, I just receive a bunch of errors, I am trying  something like:

{% set img = entry.content.type('images').first.images[0] ?? null %}

Additionally, it appears I cannot use the loop to save a variable to use outside of it, I presume this is intentional and how eager loading works. If that is the case, would I even benefit from any optimisation on the query at all if it is looping on blocks I do not need? As an example, I would normally do something like

{% set img = entry.content.type('images').first.images.first ?? null %}

Following on from whether this is worth it... I also want to get a text field on this matrix (from the first of a block type again), but, in another position in the template. Does this mean I need to do another loop again to get the data specifically for another field?

Is there a better way to deal with this?

I hope that makes sense, let me know if not I'll do my best to clarify.

Additionally, it appears I cannot use the loop to save a variable to use outside of it

This is really a separate question. Answering it anyway: you need to give the variable some value before the loop, and then it works:

{% set img = null %} {# initial value #}

{% for block in entry.pageContent %}
  {% if block.type == 'images' %}
    {% if not img %}
      {% set img = block.images[0] ?? null %}
    {% endif %}
  {% endif %}
{% endfor %}

{# img will be the first image of first 'images' block, or null #}


Is cache condition necessary to stop HTML being inserted into database cache? We currently use cache tags with a condition referencing the cache config setting:

{% cache for 1 hour if craft.config.cache %}

Is the condition necessary to stop HTML being inserted into the database cache?

No, there is a better way to do this. Set the enableTemplateCaching config value to false.

'enableTemplateCaching' => false,

With that setting disabled, all caching will be skipped.

// Won't be cached
{% cache for 1 hour %}


Partial links not going outbound I have links on a partial within my templates, but it seems to be trying to load a template when it should just be loading the outbound href of the  tag. I don't have a clue why this would be happening?

  {% if user.userWebsite %}

  {% endif %}

Will link out to mysite.com/profile/pinterest.com/username when really it should be going to pinterest.com/username

Any ideas to why?

The browser reads user.userWebsite as a relative URL, not an absolute one, I guess because your user.userWebsite field does not store the protocol, i.e.: http or https.

If you don't specify a protocol in a URL a browser must assume that it is a link to a resource on your own site. The solution is to either store the protocol within userWebsite (probably the best option), or prepend it in your template, e.g.:

href="https://{{ user.userWebsite }}"


Output number of children in a structure In my template I'm displaying all entries of a structure: ('areas').level(1) using a loop.

I would also like to display the number of children entries in each of the 'areas'.

Like: "Area 1, 4 properties", "Area 2, 7 properties", "Area 3, 5 properties" and so on.

Anyone?

If you want all the descendent too you can use:

{% set totalDescendents = entry.getDescendants().count() %}

https://buildwithcraft.com/docs/templating/entrymodel#getDescendants


Best practice for channels and structures I am wondering if there is a best practice around using channels and structures. When you have a single section you can link to that section by selecting the entry for it. For channels and structures there is no "entry" that represents the landing page where I just want to display the list of entries. Do I need to create a single section as the landing page and loop entries from my channel section in order to link to that landing page?

You basically have two options for creating a "listing" or "archive" view for your Channel or Structure sections.

The first option is to create a Single. This is in many cases appropriate, e.g. if you need to add content to the listing view in addition to the actual entry list, such as a visual banner, introductory text etc.

Inside the Single section's entry template, you'll need to pull the entries you want to display in the list using craft.entries – here's a very basic example for how the Single section's entry template could look:

{% extends '_layout' %}

{% block content %}

    {# Display some content from our Single #}

{{ entry.title }}

{{ entry.introduction }}

    {# ...and a list of entries in the "news" Section #}

Entries

        {% for newsEntry in craft.entries.section('news') %}

{{ newsEntry.title }}

        {% endfor %}

{% endblock %}

The second option is to not create a Single :) Of course, then you need to solve the problem of there not being an actual URL for your "archive" or "list" view.

There are many ways to approach this, but a simple and good solution to this problem is to leverage Craft's template routing pattern. If your Channel or Structure section's URL format is news/{slug}, and the entry template is news/_entry.html, you can simply create a template called news/index.html, and Craft will render that template for any requests to example.com/news.

Without a Single, the templates/news/index.html template will look much the same as the above example (you'll still need the craft.entries query to actually pull the entries) albeit without a pre-populated entry variable:

{% extends '_layout' %}

{% block content %}

News archive

Here's our awesome news archive

Entries

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

{{ entry.title }}

        {% endfor %}

{% endblock %}

About "Craft's template routing pattern" mentioned above; these are two important things to know about:

– Whenever Craft can't match a URL request to an entry or category (and also no dynamic routes) it'll look for a matching template path. This means that if there's no entry or category with a URL format matching the request example.com/news, Craft will look for a template with the filepath /templates/news/index.html. If that template exists, Craft will render it.

– Any template prefixed with an underscore (or in a folder prefixed with an underscore), such as /templates/news/_entry, is excluded from template routing. This means that Craft won't match the URL example.com/news/entry to the news/_entry.html template.


PHP error after adding new field I've added many fields in the past with success but today, on my local MAMP server, after adding a new field to a Matrix and saving, I'm getting a PHP error when I try to view the entry's admin page, the page preview, or try to add a new entry.

Thankfully removing that field and saving gets me back to where I was. The CMS is up to date. Here is the error when trying to view the entry's admin, I can post more if it helps (the stack trace has 70+ errors in it):

When creating a new entry, the error is also on BaseOptionsFieldType.php but line 362:

if ($option['value'] == $value)

Would anyone have any ideas for getting around this? The field I want to add is a Lightswitch but I get the same error when trying a Plain Text field.

I tried removing a few of the options from one of the Dropdowns within the Matrix and lo-and-behold, the errors are gone. Thanks so much! I guess I hit some kind of limit?


Image and italics issues in Rich Text editor since 2.5 update In addition to the lack of image resizing and the odd extra spacing, the latest Redactor implementation also lacks support for aligning images left or right.

I've also discovered any text that was previously italicized by the previous text editor disappears when rendered in the new one. If the entry is saved with the new text editor in place, all previously italicized copy disappears.

Until this implementation is remedied, I've plugged the earlier version of Redactor into this instance to stem client complaints. Doing so completely disables image placement and Live Preview, but it beats the alternative.

Is this the correct route of action in order to restore this functionality, or is there a better way? Please advise.

There is a better way! Pixel & Tonic has addressed this with the Redactor I plugin, available here: https://craftcms.com/news/running-redactor-i-in-craft-2-5

This completely restores the previous content rendering and functionality (including image sizing/alignment and Live Preview).

I understand where Imperavi is coming from, championing for cleaner data, but it just wasn't part of this project's workflow. When I start my next project fresh, I'll be using Redactor II.


Automatically subscribe users to MailChimp list? I would like to automatically subscribe all newly registered users to a MailChimp mailing list.

Install the MailChimp Subscribe plugin and add the following users.onActivateUser event listener to your site’s Business Logic plugin.

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

    if (!$user->admin) {
        $result = craft()->mailchimpSubscribe->subscribe($user->email, '');

        if (!$result['success']) {
            Craft::log('Couldn’d subscribe to MailChimp list: '.print_r([
                'errorCode' => $result['errorCode'],
                'message' => $result['message'],
            ], true), LogLevel::Error);
        }
    }
});


Email Field Being Dropped on sendMessage (Craft Contact Form Plugin) New to Craft CMS and trying to solve a mystery.  When this contact form sends, the recipients don't get the email field.  We get the others, including the consent, but the email field is missing.  Any help would be appreciated.

Here's the code.  Is there somewhere else it could be missing from?

{% macro errorList(errors) %}
    {% if errors %}
        {% includeJsFile(siteUrl~'js/validate-form.js') %}
        {% includeJsFile(siteUrl~'js/contact-scroll.js') %}

            {% for error in errors %}

{{ error }}

            {% endfor %}

    {% endif %}
{% endmacro %}

{% from _self import errorList %}

<form method="post" action="" accept-charset="UTF-8" id="ask-scigrip">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="contactForm/sendMessage">
    <input type="hidden" name="redirect" value="contact/thanks">
    <input type="hidden" name="toEmail" id="toEmail" value="{{ 'info@scigrip.com'|hash }}">
    <input id="composite" name="composite" type="text">

        Your Data Permissions

        Under the new GDPR Regulations. We require your consent to use the above data we collect from you.
        We use this data to send you various communications for product updates and marketing purposes.
        This information will be sent by periodic emails to your email address.
        To enable us to do this you must check the below consent box.
        The data we hold for you will be inline with our privacy policy which can be viewed here.

If you do not consent then we will only use your information for this enquiry and only hold it for the time it takes to finalise your request.

I Consent<input id="gdprConsent" type="checkbox" name="message[GDPR][]" value="Consent Given" style="width:30px;margin-top:17px;">

    {{ 'POST YOUR QUESTION HERE' | translate }}
    <input id="message" name="message[body]" value="{% if message is defined %}{{ message.message }}{% endif %}" required>
    {{ message is defined and message ? errorList(message.getErrors('message')) }}

    {{ 'WHAT IS YOUR EMAIL?' | translate }}
    <input id="fromEmail" type="email" name="fromEmail" value="{% if message is defined %}{{ message.fromEmail }}{% endif %}" required>
    {{ message is defined and message ? errorList(message.getErrors('fromEmail')) }}

    {{ 'TELL US YOUR NAME' | translate }}
    <input id="firstName" type="text" name="message[FirstName]" value="{% if message is defined %}{{ message.messageFields['FirstName'] }}{% endif %}" class="inp-sml">
    <button type="submit" id="submit" name="submit" value="SEND">ASK SCIGRIP </button>

    {#

    <input type="submit" value="Send">
    <button type="submit" id="submit" name="submit" value="SEND">SEND</button>

#}
</form>

If you go with the message[] array syntax, then all other fields must use the same syntax.

https://github.com/craftcms/contact-form#adding-additional-fields

So this should solve it:

<input id="fromEmail" type="email" name="message[fromEmail]" value="{% if message is defined %}{{ message.messageFields['fromEmail'] }}{% endif %}" required>


Back-up doesn't work in Craft CMS 3 on MAMP locally I installed Craft CMS 3.0.1 locally on MAMP (Apache/PHP7.0.22), but when I want to do a backup of the database it says:
"There was a problem backing up your database. Please check the Craft logs. Back-up van database".
I cound not find any logs that pin pointed the problem. How does this happen? Thanks in advance.

I have just run into a similar problem.

I'm not sure if this is what fixed it but try creating an Envvars file as per jonlivingstone's comment here https://github.com/craftcms/cms/issues/2364

Once I had done that my backup ran. I then had to switch MAMP out of FastCGI mode otherwise I got a 500 error at the end of the update process.


Configuring email (PHP Mail) with Craft I'm trying to set up a basic PHP Mail setup with Craft. I really just need it set up to handle new account activation e-mails. I can't seem to find any instructions on the Craft site or elsewhere on how to set this up specifically for Craft. Does Craft require any specific configuration for PHP Mail to work?

Thanks.

Does Craft require any specific configuration for PHP Mail to work?

No.  Craft assumes that PHP's mail function is already working if that's what you've selected under Settings->Email in the control panel.

You don't mention what the actual problem you're having is (i.e. getting an error message or email not being delivered, etc.), but there is a support article here that can help you debug both of those issues: https://craftcms.com/support/troubleshooting-email-errors


Content creation and translation workflow I've developed my Craft website locally ( in fact on a virtual machine on the company intranet, so it's accessible within the company ).
Now it's time to fill the site with contents and translate them for 7 different locales.

My boss is asking me to provide a CSV or similar structured file to let other employees and a translation agency fill the content without accessing the CMS directly.
Is this possible? Is it a good approach?
Keep in mind that the entries have some Matrix field.

Also, is it better to insert the content in the staging environment or in  developement? Or it doesn't matter?

Never used it, but probably worth looking at this plugin: https://github.com/boboldehampsink/translate

There are some related feature requests about adding this to Craft core you might want to chime in on as well:

https://github.com/craftcms/cms/issues/970

https://github.com/craftcms/cms/issues/1173


Difference between using subscript syntax and "dot" syntax when accessing attributes of a variable or advantages of usage one of them When to use

{{ variable.property }}

and when to use

{{ variable['property'] }}

Is there a difference between these methods of accessing attributes of a variable or advantages of using one of them?

They're both the same for the most part.

The only time I'd use the second way you listed is when the property is a variable.

For instance:

{% set foo = 'name' %}
{{ variable[foo] }}

This will give you {{ variable.name }}


how to concatenate multiple variables and strings I am trying to form a url parameter (for Google Maps API) from entry field data. Basically, this is what I would like to do:

{% set street = entry.address %}

{% set  city = entry.city %}

{% set urlParam = street.", ".city.", UT"  %}

Is this possible with Twig and, if so, what is the proper syntax for concatenating multiple variables and strings?

Thanks!

Another option is to use the twig join filter:

{% set urlParam = [street, city, 'UT']|join(', ') %}

join concatenates the items in the sequence with the separator of your choice in between.


How to create a Modal with a scrollbar I'm trying to create a Modal and have a question:
my code is:

Modal header

            {{ include('srgooglemaps/infobubble/addEntry'}}

<button id="newInfoBubble"  type="button" class="btn submit" value="test">new</button>

Javascript

$("#newInfoBubble").click(function(){
    $modal = new Garnish.Modal($('#my-modal'));
});

How do I manage to make overscroll auto working? My included template is higher than the modal and I would like to add a scrollbar or another option to make everything visible.

Although I agree to close this, I think Anubarak deserves an answer as to why this is not Craft related.

The Garnish Modal doesn't care what you use it for, it's just a modal. So, what Daryl and Mats is hinting at, is that you just need to style the content of the modal properly, and you'll have scroll. Which is what you've tried to do with overflow: auto on the div. But this doesn't work since the wrapping element doesn't have a height. Also, the div itself needs a height to know when to introduce the scroll.

Taking the header into account (assuming you want it fixed in the top of the modal), something like this should get you started (inline styles cause I'm lazy, these should of course go into classes):

Modal header

        (insert long content here)

Again, this isn't specific to craft, it's a pure CSS question.


Cash On Delivery for Craft Commerce Like all other CMS's Craft Commerce doesn't have a Cash On Delivery payment method by default. How can we add or create a COD method ?

Craft Commerce has a COD method called the 'manual' gateway. Make sure you set it to authorize only and it will allow a customer to check out without submitting payment. When cash or cheque is presented you can 'capture' the manual transaction payment on the order edit screen.


How to output a structure sub-navigation of current page I've got a single structure menu for my entire site which consists of a title and a single related entry. I use that to output the main menu, which uses this code:

        {% nav link in craft.entries.section('menu') %}

 {# Checks if              the page link is the same as the slug of current page #}
            {{link.title}}
            {% ifchildren %}

                {% children %}

            {% endifchildren %}

        {% endnav %}

On the top level pages, in their template they have a sidebar which should output the menu items in that main section - all singles. Is there a way to do this or do I need to create separate Structures for each section?

You first have to get the corresponding entry in your "menu" structure and then build your navigation upon that item.

Use the relatedTo() parameter for that. The entry entry model that you automatically get on that single template is the targetElement of that relation, but you should be fine using the less specific element property used with the short syntax relatedTo(myEntryModel).

{# Get the (one!) related entry from the "menu" structure #}
{% set menuItem = craft.entries.section('menu').relatedTo(entry).first() %}

{# Check if there are descendant entries #}
{% if menuItem.hasDescendants() %}

    {# Get entries to build the sub-menu #}
    {% set subMenu = craft.entries.descendantOf(menuItem) %}

    {# Output the sub menu #}

        {% nav link in subMenu %}

                {{ link.title }}
                {% ifchildren %}

                        {% children %}

                {% endifchildren %}

        {% endnav %}

{% endif %}


Can I change which 'Format' options are available in my Rich Text field? I want to update my Rich Text field so only H1, H2 and H3 are the available options in the 'Format' selector.

Is this possible?

You certainly can using the Redactor Formatting config.

Locate the config file for the Redactor setting you want to edit in craft/config/redactor and add this line:

"formatting": ["h1", "h2", "h3"],

Or any combination of elements you want to be made available.

For those reading this who can't see the Formatting option for their Redactor field, it's also worth mentioning you need to have the Formatting button set up in the same config file:

"buttons": ["format"],


Showing posts live during a date range I've tried to follow a ton of other articles posted on Stackoverflow for showing posts between 2 dates. I just can't seem to get it working and I keep getting an error of: Call to a member function getTimestamp() on boolean

{% set startDate = now | date_modify('first day of ' ~ qFilter) %}
{% set endDate = startDate | date_modify('+ 1 month') %}
{% set entries = craft.entries.section('events').postDate('<= startDate').expiryDate('>= endDate') %}

(qFilter is a url param: eg "May")

I'm trying to show posts that were live during a certain month.

You are passing a string <= startDate to the field parameter, but you actually want it to be a string <= 2016-01-01, which you can get by concatenationg the <= string with the datetime variable. So change your parameters like so:

postDate('<= ' ~ startDate) instead of
postDate('<= startDate')


Is it possible to manage language translations without directly accessing the PHP translations file? It is beautifully described in the docs how to translate static text using translation files.

As the client has no access to that file and managing a php array is not what I want them to do, I am looking for a way to make edits to the translation file feasible directly in the Control Panel.

This would allow me to set things up in the template and then hand off the actual translation work to someone else.

Yes, you probably have to write a plugin for that. But can you edit the files from a plugin? Is there any API or service available that might help?

I'm pretty new to Craft but I'll tell you what I'd try anyway for fun.

I'd create a "Translations" assets source that would hold files like es.csv.

Then, in craft/translations/es.php, I'd run through that CSV and build the array Craft wants and return it.

<?php

$path = $_SERVER['DOCUMENT_ROOT'].'/../craft/translations/translations.csv';
$delimiter = ';';
$skip_rows = 1; //skip header rows
$primary_locale_column = 0; //set primary locale column
$this_locale_column = 1; //set secondary locale column for this `lang.php` file

$translations = array();
$translations_file = fopen($path, 'r');

if ($translations_file) {
    while(($translation = fgetcsv($translations_file, 1024, $delimiter)) !== FALSE) {
        if($skip_rows != 0) { $skip_rows--; continue; }
        $translations[$translation[$primary_locale_column]] = $translation[$this_locale_column];
    }
}

return $translations;

This is totally untested.


How to edit registration form fields? I want to edit the registration form on my site. I have set up new fields and added it to the field layout under setting. However, the changes still don't appear on the registration form. Another problem is that the registration form is not an entry. Under the menu bar, the registration form seems to be just an added URL. Please help.

After adding the new fields to your field layout, you still need to update your template to display the new fields.  You can read the templating docs on the Craft website to see how to output the individual fields.


The safest way to edit core Craft files? I've been tasked with adding a column to the Entries screen to show some custom data that gets saved against each new post. To do this, I've edited craft/app/elementtypes/EntryElementType.php and added a new table attribute, which does what I need and shows the column.*

However, I'm wary though that updating Craft involves removing the /app directory and replacing it with the one from the latest release.

Is there an advised way I should make tweaks to core files like the one I mentioned? Or, is the only solution to do something like...

Add PHP comments around any core code I tweak
When preparing for an update, compare the old /app against the new one in GitHub
From there, search through the changes to find the comments I've added
For each comment I find, I should manually recreate the changes in the correct places within the new version of /app

* Just to clarify, I was using an older version of Craft when I wrote this post. Having updated to 2.6, I now see that choosing which columns to show on the Entries screen is a baked-in feature. Nice :)

You should never edit the core files (i.e. anything below /app), because whatever changes you add might be overwritten any time Craft is updated – or even worse, your amendments might conflict with new features added in Craft updates to a different part of the codebase; crashing your entire site. Seriously, don't do it.

Whenever you need Craft to do something that it doesn't do out of the box, your options are:

– Installing an off-the-shelf plugin, of which there are many
– Writing a plugin yourself (which shouldn't be too hard, if you have PHP experience)
– Finding someone else to build your custom plugin
– Adding a feature request

If you do need to write a custom plugin, probably the most important thing to know about are hooks and events, which offer ways to hook into and act upon various parts of the Craft internals and request lifecycle.

Specifically, I believe your current use case could be easily solved by creating a small custom plugin with the defineAdditionalEntryTableAttributes hook.

Here's how that could look, assuming your custom property is named customProperty (the following would go into your plugin's primary class, e.g. myplugin/MyPluginPlugin.php):

public function defineAdditionalEntryTableAttributes()
{
    return array(
        'customProperty' => "Custom label",
    );
}

With the above, you'll be able to simply add your custom property to the relevant element indexes via the little cogwheel below your Sections, under Entries inside the CP.

If you need more control over how the custom property renders (for instance, if the property returns a non-String value, you want to wrap the property value in some HTML, or you need to account for the custom property not being set for all entries, etc), you can use the getEntryTableAttributeHtml hook to refine things:

public function getEntryTableAttributeHtml(EntryModel $entry, $attribute)
{
    if ($attribute == 'customProperty' && isset($entry->customProperty))
    {
        return ''.$entry->customProperty[0].'';
    }
}


Why are my plugins not showing? I am trying to import from Wordpress, so originally installed the Import plugin which worked but I needed xml not csv. So I uninstalled that and installed another, but now no matter what plugin I try to install, nothing shows up!

Any ideas? I tried resetting cache etc.

Update: Adding more details.

I've tried to install multiple plugins since the original one, the current plugin that I have in the plugins folder is 'craftimport-master' with all the correct files inside it.

The plugins page just says "There are no available plugins." with no errors.
I've tried running Clear Caches and Rebuild Search Indexes, just in case it worked.

I also tried updating to Pro (using craft.dev) but that didn't change it either.

Here is the current file structure:

Oh and there was an error when I uninstalled the first plugin but it redirected me almost instantly so I don't know what it said.

It looks like the folder name of your plugin is wrong. Change it to just say craftimport.

The folder name should be the same as the "Whatever" part of the WhateverPlugin.php file sitting in the plugin's root folder. Except that the folder name should always be all lowercase. That's important, because some systems are case-sensitive while others are not... The only way to be certain your plugins will be detected is to use a lowercase folder name. (see this thread...)


Set EntryModel data on an element I am trying to update the value of an Entries field on an EntryModel, however I am having a lot of trouble getting it to update correctly.

I've tried allocating both an entire EntryModel and its id but neither seems to set the value, e.g.

$comment = new EntryModel();
$comment->sectionId = $commentSectionId;

$comment->setContent(array(
    'createdBy' => $user // or
    'createdBy' => $user->id
));

craft()->entries->saveEntry($comment);

Where $user is a valid EntryModel.

The comment saves fine, the createdBy field just has no value. I guess I am using the wrong data from $user but I have having a very hard time finding any thorough documentation around setting different kinds of EntryModel data.

This is the entire bit of code I have, if it helps:

class Bugr_CommentService extends BaseApplicationComponent
{

    public function post(EntryModel $user, EntryModel $ticket, $body)
    {
        $comment = new EntryModel();
        $comment->sectionId = craft()->sections->getSectionByHandle('comments')->id;

        $comment->setContent(array(
            'createdBy' => $user,
            'ticket' => $ticket,
            'body' => $body
        ));

        return craft()->entries->saveEntry($comment);
    }

}

To assign a related Element (i.e. related User, Category, Entry, Tag, Asset) the value should be set to an array of element ids (even if there is only one element).

public function post(UserModel $user, EntryModel $ticket, $body)
{
    $comment = new EntryModel();
    $comment->sectionId = craft()->sections->getSectionByHandle('comments')->id;

    $comment->setContent(array(
        'createdBy' => array($user->id),
        'ticket'    => array($ticket->id),
        'body'      => $body
    ));

    return craft()->entries->saveEntry($comment);
}


Passing value in form with amforms plugin I've created a form using amforms to ask some info about the visitor when he request a document.
I want to pass the name of the requested document in the form.

So I created the field nomDocumentEfficy and attached it to my form but I cannot get the value in my submitted forms.

Here is my form :

<div class="form-askemail contact">
    {{ getCsrfInput() }}

    {# This should always be here! #}
    <input type="hidden" name="action" value="/amForms/submissions/saveSubmission">

    {# Insert your form's handle. #}
    <input type="hidden" name="handle" value="{{ form.handle }}">

    {# This will namespace your inputs (for IDs and such), but it's not required though #}
    <input type="hidden" name="namespace" value="{{ form.getNamespace() }}">

    {# Optional: Redirect URL. Will redirect to current page by default. #}
    <input type="hidden" name="redirect" value="{{ craft.request.getParam('redirect') }}">

    {# Optional: Anti-spam protection. #}
    {{ craft.amForms.displayAntispam() }}

    {# Optional: Google reCAPTCHA protection. #}
    {{ craft.amForms.displayRecaptcha() }}

    {# Place the HTML of your fields here #}
    {{ form.displayField('email') }}
    {{ form.displayField('societe') }}
    {{ form.displayField('typeEtablissementAskEmailForm') }}
    {{ form.displayField('numeroDepartement') }}

    {# Hidden input field with my value #}
    <input type="hidden" name="nomDocumentEfficy" value="my_value">
</div>

Whenever you submit forms to Craft, your name attribute must be formatted in a certain way by adding your values to a fields[] array. In your case, the field should look like:

<input type="hidden" name="fields[nomDocumentEfficy]" value="my_value">

You can see this happening if you ever inspect a form field inside an entry in the CMS, or if you inspect the output generated by amforms' tags you're using: {{ form.displayField('email') }}

However, not all form field types get added to this array the same as a simple text or hidden field! For reference on how to format checkbox fields, date fields, or even Matrix fields, for example, you can reference this great guide on StraightUpCraft.


How to handle license when duplicating entire website I have two seperate clients on different domains but I'm developing very similar websites for each. If I duplicate the entire site and upload to new domain what is the best way of handling the license key for the duplicated site.

I'm assuming if I transfer the license, using the control panel message, then the other website's license will break.

Any help would be appreciated.

(edit: I want to pay for the license on the duplicated system without losing any data.)

I think it would be enough to delete the license.key file under

craft/config

and purchase a new license. The key file will be re-generated.

Some more info in this answer, and here is how Craft decides if it is running on a public domain


Returning entries that contain both categories I'm creating a filter and would like to return entries that must contain multiple categories (and behavior, not or). A sample url would be /events?cat=2,3.

{% set eventCat = craft.request.getParam('cat') %}
{% set events = craft.entries.relatedTo(eventCat).all() %}

Gives me "or" behavior and

{% set eventCat = craft.request.getParam('cat') %}
{% set events = craft.entries.relatedTo('and', eventCat).all() %}

Doesn't give me any results.

(updated to reflect Craft 3 syntax, thanks Robin!)

Answer for Craft 2
Your final result should not look like relatedTo('and', '1,2') but
relatedTo('and, 1, 2')

Or
relatedTo(['and', 1, 2])

So you just need to do
relatedTo('and,' ~ param)

Keep in mind to code defensively, so you might want to check if your query param is not null or something
Answer for Craft 3
relatedTo(['and', ['element' => 1], ['element' => 2]])


Get dropdown / checkbox / multiselect field values on frontend submit I would like to allow registered users to submit entries to sections. The documentation didn't mention how to get the values and labels of dropdown / checkbox / multiselect fields to show them as options on the submitting page. I can't use the entry variable because the entry is not saved yet.

You can get info about your fields using craft.fields.getFieldByHandle(). That will include a settings property, which will be an array of the field type’s settings.

The actual settings available will differ depending on the field type, but Dropdown, Checkboxes, and Multi-select fields all have the same one: options. So in each of their cases, here’s how you would loop through the options:

{% set field = craft.fields.getFieldByHandle('myFieldHandle') %}
{% for opt in field.settings.options %}
    <label>
        <input name="fields[myFieldHandle][]" type="checkbox" value="{{ opt.value }}">
        {{ opt.label }}
    </label>
{% endfor %}


Closure in plugin class/ saving and passing a public property I am struggling with closure and saving a variable.

In my class somePlugin i do have a public var $customerId , which should be updated after i execute my setUser() function. To do so i have a setter and getter function. In my init() function i do want to use the new var on a later EVENT_BEFORE_COMPLETE_ORDER event. However the variable $customerId does get reset to the default value after page reload.

How would i avoid that?

I tried using session but it seems like the session has been overwritten on reload as well

class somePlugin extends Plugin {

    public $customerId = '1234';

    public function init() {

        parent::init();
        self::$plugin = $this;

        Event::on( Order::class, Order::EVENT_BEFORE_COMPLETE_ORDER, function( Event $e ) {
            $order             = $e->sender;
            $customerId        = $this->getCustomerId();

            // on every page reload it does get reset to the default var, what is not wanted
            $order->customerId = $customerId;
        } );
    }

    public function setUser( $userId ) {

        self::$plugin = $this;

        // get userModel by userId
        $userModel = Craft::$app->users->getUserById( $userId );

        // check if  commerce record for craft user exists
        if ( ! $this->customers->getCustomerByUserId( $userId ) ) {

            // create and save new customer
            $newCustomer       = new Customer();
            $newCustomer->user = $userModel;
            $this->customers->saveCustomer( $newCustomer, false );
        }

        // store customerId
        $customerId = $this->customers->getCustomerByUserId( $userId )->id;

       // sets the new and wanted it wich gets overwritten by page reload
        $this->setCustomerId( $customerId );

    }

    public function setCustomerId( $customerId ) {
        $this->customerId = $customerId;
    }

    public function getCustomerId() {
        return $this->customerId;
    }
}

I figured that i could just use Craft::$app->getSession()->set( 'key', $value ); to store the vars in the craft session.

class somePlugin extends Plugin {

    public function init() {

        parent::init();
        self::$plugin = $this;

        Event::on( Order::class, Order::EVENT_BEFORE_COMPLETE_ORDER, function( Event $e ) {
            $order             = $e->sender;
            $order->customerId = $this->getCustomerId();
        } );
    }

    public function setUser( $userId ) {

        self::$plugin = $this;

        // get userModel by userId
        $userModel = Craft::$app->users->getUserById( $userId );

        // check if  commerce record for craft user exists
        if ( ! $this->customers->getCustomerByUserId( $userId ) ) {

            // create and save new customer
            $newCustomer       = new Customer();
            $newCustomer->user = $userModel;
            $this->customers->saveCustomer( $newCustomer, false );
        }

        // get and store customerId
        $customerId = $this->customers->getCustomerByUserId( $userId )->id;
        $this->setCustomerId( $customerId );

    }

    public function setCustomerId( $customerId ) {
        Craft::$app->getSession()->set( 'customerId', $customerId );
    }

    public function getCustomerId() {
        return Craft::$app->getSession()->get( 'customerId' );
    }
}


Author saved as NULL when updating entries from a plugin I'm using a custom plugin with a service and controller to save relational fields to entries. I'm able to do this just fine, but when it saves an entry, it sets the author as NULL in the database and it no longer shows in the author's list of authored entries.

I've tried to both not set the author at all and to manually set the author to the previous author. Craft gives me an Internal Service Error saying "Property 'Craft\EntryModel.author' is read only." when trying to set the author in the code. Removing the retrieval and setting of the author saves the entry but marks the author as NULL

Has anyone else faced this? Is it a bug?

For reference, here's the heart of this service's code:

    $criteria3 = craft()->elements->getCriteria(ElementType::Entry);
    $criteria3->id = $kitId;
    $currentKit = $criteria3->first();
    $currentAuthor = $currentKit->author;

    $kit = new EntryModel();
    $kit->sectionId = '6';
    $kit->id = $kitId;

    $kit->author = $currentAuthor;
    $success = craft()->entries->saveEntry($kit);

Josh Angell's suggestion did work, I was just testing it on an entry that already had been updated with a NULL author. (Thanks Josh!)

For the record, I used $currentAuthor = $currentKit->authorId; to get my previous author, and then set the author with $kit->authorId = $currentAuthor. This does seem to maintain the author entirely.


Disabling caches in Safari results in server errors while developing Craft 3 site I'm running into a vexing issue while developing a personal site in Craft. I have a new Craft 3 site, installed manually. I'm developing live on the server in a dev subdomain. My .env sets the site to "dev" mode.

It's been awhile since I've worked on a front-end; one thing that's been an issue is either Safari or Craft caches the CSS while I'm coding. To prevent the cache from loading I've used the "ignore the resource cache while loading resources" button in the Network pane of the Webkit inspector. A few times after reloading the page, I begin to get server errors. The server errors are yii exceptions for a missing template of internal_error.html, which suggests a server error and not a Craft error specifically.

I've searched through the logs and although I can see where Craft throws the exception, I can't see what is causing this. The headers on my network simply say that the main site URL is throwing a 404. My server log says:

  [Thu Mar 12 11:29:11.886937 2020] [core:error] [pid 28286] [client
  xx.xxx.xx.xxx:xxxxx] End of script output before headers: index.php

Thinking this might be a permissions issue I started from scratch with a Composer-installed Craft. All was fine until I used the cache button on the Network pane again, and the errors returned.

If I change the mode to "production" from "dev," the errors go away, and as far as I can see no new error is created in the server or Craft log. So I can develop in production mode but I do find the dev mode useful.

I've manually cleared the cache from storage/runtime and cleared the generated files in cpresources. I've also cleared the cache from the backend admin when logged in via production mode. This doesn't have any effect.

I should add the only thing I haven't tried is to disable Safari's caches while running the site in production mode; if it's related I don't want to break the only method I have on working on the site.

Any help here is greatly appreciated!

If I change the mode to "production" from "dev," the errors go away,
  and as far as I can see no new error is created in the server or Craft
  log. So I can develop in production mode but I do find the dev mode
  useful.

It sounds like you're changing the environment variable ENVIRONMENT, e.g.:

ENVIRONMENT="dev"

This actually doesn't do much, it's just an arbitrary name for the environment that Craft is running in. You could call it fluffybunny and no one would mind. The only thing it affects is what settings might be used in you multi-environment config files like config/general.php.

I'd suggest reading over the Flat Multi-Environment Config for Craft CMS 3 article

Also for log file reading, the article Zen and the Art of Craft CMS Log File Reading may be useful as well.


500 error on updating Craft I'm trying to update from 2.3.2640 to 2.3.2644, but I get a 500 error

Internal Server Error
The server encountered an internal error or
misconfiguration and was unable to complete
your request.
Please contact the server administrator,
you@example.com and inform them of the time the error occurred,
and anything you might have done that may have
caused the error.
More information about this error may be available
in the server error log.

When I look a the logs I can see that the backup was successful

2015/05/20 13:23:15 [info] [application] [Forced] Finished backing up database.
in /xxx/craft/app/services/UpdatesService.php (399)
in /xxx/craft/app/controllers/UpdateController.php (317)
in /xxx/craft/app/etc/web/WebApp.php (869)

And the sql file is in the backup folder.

Any idea where I might look to fix this error?

EDIT: I see that it's timing out at 30 seconds. I've set my php file to have max_execution_time = 60, but it's still timing out at 30 seconds...

Step 01.
Open your php.ini file.
File path for php 5.6: /etc/php/5.6/apache2/php.ini
File path for php 7.1: /etc/php/7.1/apache2/php.ini

Step 02:
Then increase max_exection_time from 30 to 300 or other as you like.

Step 03:
Restart your server sudo service apache2 restart

Step 04:
Go to your web's root directory then run this command composer update

Now browse your site.


Assign a user group to a structure entry. Restrict permission front end page to that same group I'm working on a website for a school. Each group has a specific page that has video's for that group only. Members of that group do not need access to the CP. First I noticed that I can only assign specific members to an entry, using the Users field. I'm not able to assign a group at once.

How can I make it possible for the teacher to assign a group to a video through the CP (not the code), and that only that group can view the page after login?

As far as I know there is no way to assign a 'group' using an entries fieldType. What I would likely do is create a category group called 'User Groups' (userGroups) that mirror my groups, with fields for 'title' and 'groupId'.

Group Title 1 -> 1,
Group Title 2 -> 2,
Group Title 3 -> 3,
etc.

(Unfortunately, I think the only way to get the groupId is to look in the database craft_usergroups table. Although the code below could probably be adapted to use the group handle if needed.)

Then create a categories fieldType called 'authorizedGroups', and add it to the video channel's fieldLayout (or wherever else you need it). The client would then be able to select groups via the authorizedUserGroups field that have authorization to the video.

In your template(s) you can then check for videos related to the authorizedGroups that match the currentUser.group and display content accordingly.

First, on your videos index page you would only want to only show links to the videos that the user has authorization to view.

{% if currentUser %}
    {# create an array of the currentUser.groups Ids #}
    {% set currentUserGroupIds = [] %}
    {% for group in currentUser.groups %}
        {% set currentUserGroupIds = currentUserGroupIds|merge([group.id]) %}
    {% endfor %}

    {# find all userGroupCategories that match currentUserGroupIds #}
    {% set userGroupCategories = craft.categories.group('userGroups').find({
        groupId: currentUserGroupIds
    }) %}

    {# find all the videos related to userGroupCategories #}
    {% set entries = craft.entries.section('videos').relatedTo(userGroupCategories) %}

    {% for entry in entries %}

{{ entry.title }}

    {% endfor %}

{% endif %}

Then on the video detail page you would use a conditional that redirects any unauthorized users to a 401 page (or to any other page that you choose).

{% set userIsAuthorized = false %}
{% for group in entry.authorizedUserGroups %}
    {% if currentUser.isInGroup( group.groupId ) %}
        {% set userIsAuthorized == true %}
    {% endif %}
{% endfor %}

{% if not userIsAuthorized %}
    {% redirect 401 %}
{% endif %}

{# display video #}
...

Update: There was a significant code error that did not account for the fact that user.groups returns an array of groups rather than a single group. I rewrote the code to handle this. Untested, and probably still contains errors, but should be closer at least.


How to manage a large database when upgrading from 2.0 to 2.1 I am trying to upgrade a site from 2.0.2551 to 2.1.2570. I have ~18k entries and ~28 elements. The upgrade process seems to want to save all the elements again as far as I can tell, is there any way to avoid this or make it quicker? Is there some magical SQL I might play with to do it all?

At present I've had it sat for 14 hours before I gave up...

Incidentally I can legitimately reduce the number of entries to about ~3k and the elements to ~11k as I can just re-import those from an API service - I have tried this and it still takes an awfully long time.

Any advice or previous similar situations you people have run in to would be most helpful :)

In my specific case - upgrading from 2.0.2551 to 2.1.2570 - the issue was caused by there being millions of rows in the craft_entryversions table. One of the migrations in the update needed to loop through every row in that table and do something to it and therefore it took ages.

Simply emptying that table solved the upgrade process for me.

Caveats

Obviously this deletes all your entry versions...so, each entry will just exist at its last known 'live' state. This wasn't a problem for me - but might be for you.

Its worth noting that this shouldn't affect any drafts users might have made as they are stored in a separate craft_entrydrafts table.

Thanks to Fred Carlsen for helping me think aloud...


Admin Main Content hidden Installing Craft 2.2 succeeded. But every main content in the admin is hidden. Example Dashboard (copy & paste from ff debug, which shows only containers without sub nodes!):

 <---- display: none

 <---- display: none

 <---- display: none

 <---- display: none

 <---- display: none

When display: none is disabled in FireDebug I see evreything how it should.

What is wrong?

Seems to be a browser bug. Dashboard is not working with Firefox 20. With Firefox 31 admin is working.