Plugin CP page causes white screen I'll start off by saying my plugin is working perfectly locally. The problem is when I upload to my server. My plugin is for a contact form. It handles the submission, and logs the entry in the db.
I have a page in the CP for it as well - this is the page that is giving me the white screen.
With devMode I am seeing this in the logs:
[error] [exception.Craft\HttpException.404] exception 'Craft\HttpException' in /path-to-my-site/craft/app/controllers/TemplatesController.php:59

So I looked up that file, and to me it seems that the system can't find a template?
I don't get any errors - although when I try to submit my form, I do get a 500 error. Could it be a permissions problem?
EDIT
Everything else in the entire site/app is working perfectly, so I know it's something with the plugin page.
My plugin "settings" page renders/works fine. It's when I click on the top "tab" to access my plugin's page within the CP that fails.
EDIT 2
I'm wondering if it's a case-sensitive thing now though. I don't see that exact error in the log file anymore.
I know with CodeIgniter, locally things work great, but when I upload to my server (CentOS) I get white screens. It's because of the case is all strange.
I have followed the suggested guidelines for plugin development:
controllers
    ContactFormPlugin.php
    controllers
        ContactFormController.php
            class ContactFormController extends BaseController {...}
    models
        ContactFormModel.php
            class ContactFormModel extends BaseModel{...}

   records
        ContactFormRecord.php
            class ContactFormRecord extends BaseRecord{...}

   resources
        ...

   services
         ContactFormService.php
             class ContactFormService extends BaseApplicationComponent {...}

   templates
       ...

   variables
       ContactFormVariable.php
           class ContactFormVariable {...}

...and so on.
My host is Rackspace, has anyone experienced this?

Brad, Thank you again for your help.

I found the problem, although I'm not sure of "why". In my service file, I have this line:

$email->body = craft()->templates->renderString($settings->welcomeEmailMessage, ['firstName' => $contact->firstName]);

After digging though log file(s), I found the error. "Unexpected '['"

It needed to be this:

$email->body = craft()->templates->renderString($settings->welcomeEmailMessage, array('firstName' => $contact->firstName));

Because everything was working perfectly on my local machine, (newer version of php) I wonder if that's the root cause.


Request the url of a channel index How can I request the url for a channel index page from another page. I got this message asked on twitter towards craft, but they misunderstood my question.

The came back to me using craft.request.getSegment(x), but this will only work if I would like the index page of a channel when I'm on the entry page of this channel.

But how would I get the url for the "news" channel index page, when I'm in the "projects" channel section (either the index or an entry) of the site?

News is an entry-field of projects btw, so that we can show news related to a project on the site.

There is no predefined 'index' page for channels. Channels are simply a collection of entries. If you want an index page then you will need to create it: either as a single, as an entry within another structure, or as a stand alone template in your templates directory (i.e. craft/templates/news/index.html or craft/templates/news.html). In any case, the url (or uri) is going to be whatever you have defined it as. (i.e. mysite.com/news/). See craft's routing documentation for more info on how requests are routed.


Can you lookup the value in a key-value array with the value in an entry field? This might be impossible, but can you lookup a value in a key-value array with the value in a craft entry field? And perform math with it in twig? I'm trying to simplify my template code.

I have a key value array like so

{%
set aspectRatioSetting = {
    'four_three' : '0.75',
    'three_two' : '0.666666666667',
    'sixteen_nine' : '0.5625',
    'one_one' : '1'
} %}

And I'd like to be able to use those values in a math operation, the specific value looked up by a value in a custom entry field.

{% set transformParams = { width: 1250, height: 1250 * aspectRatioSetting.four_three } %}

where the value of the "four_three" key in the array is used in the math operation. Only the specific key would be set by the value in an entry field.

{% set transformParams = { width: 1250, height: 1250 * aspectRatioSetting.(entry.aspectRatio) } %}

There's not a good way for me to type it up because this clearly doesn't work. I'm just wondering if it's somehow possible.

Or maybe I'm just overcomplicating things in an attempt to simplify things : /

Two options here ...

{% set transformParams = { width: 1250, height: 1250 * aspectRatioSetting[entry.aspectRatio] } %}

Or just give the select field a value that represents the number, not the word. So set a value of 0.75 instead of four_three, and let the label be Four/Three (or whatever seems fit).


Craft 3 auto-creates sub-folders in assets. How can I prevent this? I use Google storage for photos. The Google storage volume is mapped to a bucket's subfolder.

Unfortunately these appear as subfolders in assets, along with a set of repeated folder structure. I did not create these.

Any way to prevent CraftCMS from creating them? What is the cause they get created?

P.S. Is it possible that they are the remainder of subfolders which I created on the filesystem before setting up the assets to use google storage? I did delete the local storage assets volume between creating the google storage one. But, the local storage did have the ahtletes/photos in the local assets folder.

At this time, the local assets folder does not have the athletes/photos subfolder.

I am trying to understand what action or process creates these folders?

My guess would be your Asset Indexes are out of sync.

If you go to Settings->Utilities in the Control Panel, there is one that says "Update Asset Indexes".  Click it, let it run and you might be prompted to resolve some out-of-sync indexes.  Once you do that, it should work normally.


How would you template for Infinite Scroll? I want to integrate Waypoints JS's Infinite Scroll instead of using traditional pagination.  I think the Straight Up Craft site uses this approach on its blog.

How might you template the following HTML to work with CraftCMS?  I know how to limit or not limit the number of entries, but how do you template to load each successive group of (say) 12 entries as you reach a waypoint - that is the "infinite-more-link"?

...

More

Got it.  Using the CraftCMS paginate example - I just needed to add the pagination url for the next page.


Advanced search returning 'Key "1" for array with keys "0" does not exist' I have an advanced search that searches real estate properties by the usual criteria: price range, Bedrooms, Bathrooms... In the form, the default is "Any" if they don't care about a particular option.

On the results page, I'm checking for a null value in case an option wasn't selected. Despite this, I'm still getting the message 'Key "1" for array with keys "0" does not exist' if the price option is missing. What is causing this?

My search results page looks like this:

{% set price = craft.request.getParam('p') %}
{% set price = price ? price|split('-') %}

{% set br = craft.request.getParam('br') %}
{% set br = br ? br %}

{% set ba = craft.request.getParam('ba') %}
{% set ba = ba ? ba %}

Search Results

{% set searchResults = craft.entries({
    section: 'properties',
    propertyPrice: price ? ['and', '>= ' ~ price[0],'<= ' ~ price[1]],
    bedrooms: br ? [ 'and', '>= ' ~ br ],
    bathrooms: ba ? [ 'and', '>= ' ~ ba ],
    order: 'score'
}) %}

{% if searchResults|length %}

    {% for entry in searchResults %}

{{ entry.title }}: {{ entry.propertyPrice|currency('USD', true) }}: BR: {{ entry.bedrooms }}, BA: {{ entry.bathrooms }}

    {% endfor %}

{% else %}

No Results Found

{% endif %}

This error could happen if the p param is set to something, but the value doesn’t actually contain a hyphen.

If you want to find out what the problematic value is, enable Dev Mode and then check your browser console > Application Log > GET Info or POST Info (depending on the request type).

To make your code more bulletproof you can replace this line:

{% set price = price ? price|split('-') %}

with:

{% set price = (price and price matches '/-/') ? price|split('-') %}


Search query for entries doesn't seem to work correctly In my project I have a tickets which are edited in multiple steps where each step has it's own front end for. Now, of course. to continue editing an ticket I am required to fetch that exact ticket.

To accomplish this I have a search form include which will be displayed before the form is showed. When the search form returns an entry the form is shown, when this fails the search form include will be shown again.

Lastly: The search does work when I search for an entry where the title does not contain a spacebar, So:

When the title is 'Test' I can find it, when the title is test ticket I can't find it using the search form, even though they do both exist!

My code:

General.php settings:

'defaultSearchTermOptions' => [
    'attribute' => 'title',
    'exact' => true,
    'subRight' => false,
    'subLeft' => false,
],

My search form:

<form novalidate>
    <input id="search" type="search" name="ticket_number"/>
    <button type="submit">Search</button>
</form>

My URL after submitting the form:

domain.com?ticket_number=ticket+number+test+search

My page:

{% set searchQuery = craft.app.request.getParam('ticket_number') %}
{% set ticket = craft.entries().search(searchQuery).section('ticketLog').one() %}

{% if ticket|length %}

Start Picking - {{ ticket.title }}

Fill in this form to start picking.

                    {% include '/_components/includes/form' with {
                        'redirect' : siteUrl,
                        'section_handle' : 'ticketLog',
                        'fields' : [{
                            type : 'datetime',
                            handle : 'pickingStartTime',
                        },{
                            type : 'user',
                            title : 'Picker',
                            query : 'teamleader',
                            required : 'required',
                            size : '12',
                        }, {
                            type : 'submit',
                            text : 'Save Ticket',
                        }]
                    } %}

{% else %}

Your search for “{{ searchQuery }}” didn’t return any Tickets, please try again below.

    {% include 'ticket_log/forms/search_form.twig' %}
{% endif %}

Hope someone sees what I am doing wrong there!

I think the problem originates from the space in your search term: test ticket.
To verify that, could you try altering your query to either

.search('"' ~ searchQuery ~ '"')

Or

.search('fieldHandle:"' ~ searchQuery ~ '"')

The latter can be used if the search has to take place in only one field.


Translating a section's title field on save For a Single section's entry type that has the title field hidden, I'd like to translate the generated title, as per the entry's locale.

I've currently got the following in the entry type's "Title Format" field:

{section.name|t(language=locale)}

However, this doesn't translate the section.name as per the entry's locale, it appears to use the current CP locale instead (i.e., if the CP is currently rendered in English, it'll use the English translation for entries in all locales). However, if I use something like

{section.name|t(language=locale)} ({locale})

the latter locale value (inside the parenthesis) does reflect the entry's locale (it'll print something like Section Name (no) for the Norwegian version. So that's a bit odd.

Also, I've tested with a hard coded string for the t filter's language parameter (i.e. {section.name|t(language="no")}), which works as expected.

Not sure what's going on – though I'm guessing that the locale variable passed to the translation filter is somehow null (in which case Craft will use the current locale). How can I translate an entry type's Title Format based on the entry's locale?

Figured out something that works, though I can't explain why:

{{ object.section.name|t(language=object.locale) }}

Update

Here's how to do it for Craft 3:

{{ object.section.name|t('site', language=object.site.language) }}


Formatting postDate using the ElementAPI plugin Building a small AngularJS app and using the ElementAPI plugin for the first time.

I can set 'postDate' => $entry->postDate which gives me

postDate : {
   date: "2015-12-10 07:04:02.000000",
   timezone_type: 3,
   timezone: "UTC"
}

as an example.

Now I can access this date in Angular by doing {{note.postDate.date}} but obviously it's just a string so I can't use any native Angular filters for formatting.

Is there a way I can access the postDate with a date format? What options do I have?

$entry->postDate will give you the postDate property of the EntryModel, which itself is a DateTime object.

The JSON transformer will do its best to convert that object to JSON by returning its visible properties, which produces the JSON object in your example.

Angular has built-in date filters, but it requires the input data to be in a recognized format. So, what you really want in your JSON - rather than a representation of the whole DateTime object - is a more primitive value that Angular knows how to interpret as a date: You need a timestamp.

Luckily, you can easily access the timestamp of the PHP DateTime object in your transformer, like this:

'postDate' => $entry->postDate->getTimestamp() * 1000

(We're multiplying the timestamp by 1000 because Angular wants the timestamp to represent milliseconds; PHP gives us the timestamp in seconds.)

Then, in Angular you can use the date filter to change the format as desired, which in your front-end code would look something like: {{ note.postDate | date:'medium' }}


Craft criteria for asset folders In my plugin, I would like to search a folder.
However, I cannot find any information about the criteria for folders.
Are there any documentation or something?

$n = Craft::$app->assets->findFolder(array(
    'name' => $folder,
    'parent' => $p_folder
));

My code is like this. Folder name is not unique, so I have to also use its parent.
However, I do not know how to include parent folder in the criteria. "Parent" is not correct.

Check /vendor/craftcms/cms/src/models/FolderCriteria.php Class for reference. I guess most of craft's documentation lies in code.

Or you can visit https://docs.craftcms.com/api/v3/craft-models-foldercriteria.html
which is the same thing.

check table "yourprefix_volumefolders" for data type of FolderCriteria.


What's the trick to importing an entry with a categories field? We are using Hampsink's Import plug-in (0.8.33) and we have a very simple CSV for testing. One row, three columns. One of these columns contains a comma-separated list of categories. These are top level, no heiarchy.

We've tried the titles:

Provider Id,Provider Name,Service Areas
62686,Walgreens,"Defiance County,Erie County,Fulton County,Henry County,Lucas County,Ottawa County,Paulding County,Sandusky County,Williams County,Wood County"

We've tried the slugs:

Provider Id,Provider Name,Service Areas
62686,Walgreens,"defiance-county,erie-county,fulton-county,henry-county,lucas-county,ottawa-county,paulding-county,sandusky-county,williams-county,wood-county"

Category field always ends up blank after an otherwise successful import.

Yes, categories are set and have their own URL. Since there is no heirarchy, that is set to simply {slug}

We've read the several, several related posts and questions about this and there seems to be a lot of frustration around importing entries with categories. Yet still... What are we doing wrong? What's the trick?

Craft CMS 2.6.2931

It's the modifyImportRow hook. If one uses that sample code in the Read Me, related categories will not import.

So we will have to run at least two imports, one with our Import Helper that uses the hook enabled  (for tables, booleans, dates, etc.), and one without, in order to append the related categories.

Unless someone can provide better example code to exclude an entry category field, but I can't think of how right now.


Contact Form - ReplyTo or Output fromEmail So I have a contact form set up in Craft using the Contact Form plugin. I have it rigged up with Mandrill as the SMTP provider and unfortunately with the notifications, the from email address is getting stripped out of the headers by Mandrill. So there's no way to determine who the email came from in order to reply to that person.

So my question is - is there a way to set the replyto to the fromEmail OR is there a way to output the from: email address in the resulting notification message?

Many thanks in advance from me and the client dealing with it!

Cheers,
J

Not without hacking (boo!) or forking (yay!) the plugin.

Currently, the fromEmail is being set from the email address set in the plugin's setting.

$email->fromEmail = $emailSettings['emailAddress'];

And the replyTo is being set to the email that was supplied on the front-end contact form.

$email->replyTo   = $message->fromEmail;

This is done because some email servers will see that the from address is different than the domain the email originated on and wrongly mark it as SPAM.

You'd adjust those however you need.

If you want to output the email in the message body, you'd just need to add it to the $message->message property in the controller.

Alternatively, you can use a more robust form building solution.


Rename Entries to Content on CP top menu A purely cosmetic change, but just wanted to know if its possible to change the menu item for Entries to something like Content? From a client point of view, I just know some will beg me to change this :)

Would also be handy to remove the Dashboard altogether as well for some cases.

For custom "cosmetic" changes on the Control Panel there's these two Plugins by Lindsey DiLoreto:

Control Panel JS
Control Panel CSS

.

You can do both, hiding and renaming of menu items with CSS:

#nav-dashboard {
  display: none;
}

#nav-entries a,
#nav-entries a:hover,
#nav-entries a:active {
  color: transparent;
  word-spacing: -9999px;
  letter-spacing: -9999px;
}

#nav-entries a:after {
  content: "Content";
  color: #d7d9db;
  word-spacing: normal;
  letter-spacing: normal;
}

#nav-entries a:hover:after,
#nav-entries a:active:after {
  color: #fff;
}


Getting ancestors for manually set parent in template I have a a few pages outside of a structure but I want to display a breadcrumb for it as part of a structure. I am currently setting the parent page like so:
{% set parent = craft.entries.section('pages').slug('phone-directory') %}

{{ parent.ancestors }}

But when I loop through to get the ancestors it is only getting the current parent not all ancestors? Any idea how to achieve this?

The structure is
Staff
     Phone Directory

The reason I am trying to do this, is the 3rd level pages are either category pages or is a single with some specific routes. I want to manually set the real parent in the template, so I can get the ancestors for the breadcrumb trail as though it is part of the same section.

How can I manually set the parent entry in the template and get the ancestors from this entry?

**** UPDATED ****
This is an update on the above to show my exact code and what isn't working and How I expect it work...If anyone ca shed some light?

So by default I am getting my breadcrumbs like so;

{% if entry is defined and entry.section.handle != 'homepage' %}
{% set crumbs =  parent.ancetors ?? entry.ancestors|default([]) %}
{% set crumbDivider = '
/
' %}

You are in:

Home

    {% for crumb in crumbs %}
    {{ crumbDivider|raw }}

{{ crumb.getLink() }}

    {% endfor %}
    {{ crumbDivider|raw }}

{{ entry.title ?? category.title }}

{% endif %}

This works as expect for normal standard entries. For example, within my Pages structure I have a parent of News with a Child of Internal News and on the Internal News page, the breadcrumb is reflected as;
Home / News / SWH Internal News

Now on the news entry pages I want the breadcrumb to read as follows;
Home / News / SWH Internal News / {{ Entry Title }}

I thought by setting the parent on the news/_entry.html template to the SWH Internal News page like so;
{% set parent = craft.entries.section('pages').slug('archive') %}

Would then give me the ancestors of News / SWH Internal News but instead it only outputs SWH Internal News.

As @Robin Schambach said, you need to loop through the ancestors.

{% set parent = craft.entries.section('pages').slug('phone-directory') %}
{% for ancestor in parent.getAncestors() %}
    {{ ancestor.title }}
{% endfor %}

This won't output the Phone Directory entry since you're just looping through its ancestors. So to complete the breadcrumbs you'll need to add
{{ parent.title }} after the loop.


Displaying assets from Craft's cart AJAX response So, I'm currently building out an eCommerce site for a client. I'm adding products to the cart via AJAX. I'm then sliding out a 'Cart' view panel with the current cart contents, which is being updated with Craft's JSON response for the cart. (Via response.cart)

My problem is this: I need to display the thumbnail image of a product, and there doesn't seem to be anywhere I can get the asset field (or any fields) associated with the product. There is no purchasable key in the cart object, just a purchasableId. I've looked in the snapshot object within lineItems, and in the product object within that snapshot object. There doesn't seem to be any asset field (or any field) attached to this information at all.

I know I can make an additional request to fetch that information, but I'd like to avoid that if at all possible; I'm hoping it's just buried somewhere in the response.

Any help is greatly appreciated! Let me know if I need to clarify something.

The cart response definitely does not include direct access to fields on the product.  You will need to make an extra request for the information...of course you'd need to make an extra request for the image itself anyway.

One easy way of implement what you want is to simply update your cart view by ajax instead loading a template into it (rather than targeting values and using the response.cart object).  In that template you would just get the cart as normal, and therefore have access to all the product fields via that as you loop through the lineitems.


Question regarding member-owned shared assets Complicated question regarding asset sharing for a client proposal.

The website to be built will contain reports uploaded by a super-admin. These reports will be PDFs, tagged by year and be about specific users. The users that the reports relate to will be registered members of the site, and will be able to view reports regarding themselves.

Users will be able to log in to their members area of the website (front-end), and send requests to view other users' reports, and approve requests from other users to view their own reports.

Example

User1 has a login to the site, and has access to user_1_report.pdf
User2 logs in and sends a request to User1 to view user_1_report.pdf
User1 receives a notification in their members area and can click Approve / Deny
User2 gains access to the user_1_report.pdf as a download link in their members area.

Can anyone suggest how this might be implemented? I'm assuming that it needs to be done with a custom built plugin but I'd love to know if it's possible without.

If it is plugin-only and there are any Craft plugin developers available, let me know as there is a budget available for someone to build that area of the site if necessary.

As you've noted, this is a complex and would require a proper discovery and planning phase to sort out all the details.  Here are a few thoughts on each stage of the process that you discussed. It looks like Luke has approached the problem in a similar way in the comments above.

User1 has a login to the site, and has access to user_1_report.pdf

This could potentially be handled by a Craft Entries or Users Relations field.  You could let somebody relate a Report to the specific User who should be able to see it, or allow a User Profile to be related to several differnet Reports.  In whichever case, you could limit who has visibility to the reports in the front-end by only displaying Reports to Users who have the right relationship to them.

User2 logs in and sends a request to User1 to view user_1_report.pdf

This will need to be handled with a plugin.  I would approach the problem in two steps.  The first part of the problem is an email notification problem, and the second part is an action that will required changing the relationship or permissions of who has access to something. Depending on how secure you need things to be, there may also be a validation component to ensure that only a User that has received an invite is able to accept that invite.

There are likely some Email plugins that could help get you started with the Email notification part of this. We have built similar authentication workflows using Sprout Email. For the particular approval action that you need, it's likely you'll need to approach that as a separate custom plugin that handles the specific action you need.

User1 receives a notification in their members area and can click Approve / Deny

This is mostly addressed in my previous comment. When you trigger the notification email, you can make sure that the notification email includes a link to help the user Approve/Deny the request. In my discussion above, those Approve or Deny actions would probably be links to controller actions that handle the behavior you need, or to a page on your site that then allows the user to trigger the right action.

User2 gains access to the user_1_report.pdf as a download link in their members area.

Once the approval workflow is sorted out, this will likely just be handled in the same way as the first scenario – via a Relations field or some permission and the standard Twig code needed to output that data.  One option could be to have an "Approved Users" field on a Report Entry, and your custom action would trigger adding the invited user as a Relation to the Report that they were invited to.


Is there a way to speed up password hashing? I am setting up a system that migrates users from an external source and have determined the most time expensive part is when the UsersService _setPasswordOnUserRecord method hashes the password

$hash = craft()->security->hashPassword($user->newPassword);

This is taking about 2 secs where the rest of the operation for saving a user is about .2 sec. There are close to 10k users to it's really adding up! Is there any way to use a faster type of hash or bypass the hashing, or am I out of luck?

example:

    $user = new UserModel;

    $user->firstName    = "First";
    $user->lastName     = 'last';
    $user->newPassword  = '123456';
    $user->email        = 'email@email.com';
    $user->username     = 'username';

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

There is a general config setting for this:

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

Setting this to the minimum value:

'blowfishHashCost' => 4

made the hashing time negligible.


Deleting a user's profile photo via frontend in Craft3 I am having the hardest time allowing a user to delete their profile photo with Craft3. I have tried to follow this thread's answers : Allow user to change or delete their photo for their profile from the front end. But it is not working. I guess because some stuff has changed since Craft2.

Here is my twig code :

    {% if isEditable %}
        <form method="post" enctype="multipart/form-data" accept-charset="UTF-8">
            {{ csrfInput() }}
            <input type="hidden" name="action" value="users/save-user">
            {{ redirectInput('profil/'~currentUser.id) }}
            <input type="hidden" name="userId" value="{{ currentUser.id }}">

            {% macro errorList(errors) %}
                {% if errors %}

                        {% for error in errors %}

{{ error }}

                        {% endfor %}

                {% endif %}
            {% endmacro %}

            {% from _self import errorList %}

            <input type="hidden" name="deleteUserPhoto" id="deleteUserPhotoInput" value="">
            {% if account is defined %}{{ errorList(account.getErrors('deleteUserPhoto')) }}{% endif %}

                        Modifier ma photo de profil

            <input id="profilePhotoInput" type="file" name="photo" accept="image/*">
        </form>

        delete

    {% else %}

    {% endif %}

And the Javascript code :

$('.delete-profile-photo-btn').on('click', function () {
    var deleteUserPhotoInput = $("#deleteUserPhotoInput");
    deleteUserPhotoInput.val('1');
    deleteUserPhotoInput.parents("form").submit();
});

With this code, I get no errors, and the profile image doesn't delete.

I then decided to try and reverse engineer the admin panel and see how it was done there. I came up with the following form :

<form id="deleteUserPhotoForm" method="post" enctype="multipart/form-data"
      accept-charset="UTF-8">
    {{ csrfInput() }}
    <input type="hidden" name="action" value="users/delete-user-photo">
    {{ redirectInput('profil/'~currentUser.id) }}
    <input type="hidden" name="userId" value="{{ currentUser.id }}">
</form>

And the Javascript :

var form = $('#deleteUserPhotoForm');

var data = form.serialize();
userFormAjaxCall(data, function (status, resp, xhr) {
    console.log(status);
    console.log(resp);
    window.location.reload(true);
});

With this code, it seems to work, but I get this error message (not sure what the equivalent in english is).

  Impossible de trouver le modèle “users/_photo”

What is the cleanest and simplest way I can allow a user to delete their profile photo?

The input name has changed from "deleteUserPhoto" to "deletePhoto" in Craft 3.

Here is my updated working Twig code if anyone needs it :

<form method="post" enctype="multipart/form-data" accept-charset="UTF-8">
    {{ csrfInput() }}
    <input type="hidden" name="action" value="users/save-user">
    {{ redirectInput('profil/'~currentUser.id) }}
    <input type="hidden" name="userId" value="{{ currentUser.id }}">

    <input type="hidden" name="deletePhoto" id="deleteUserPhotoInput" value="">

    <input id="profilePhotoInput" type="file" name="photo" accept="image/*">
</form>

And my Javascript code :

$('.delete-profile-photo-btn').on('click', function () {
    var deleteUserPhotoInput = $("#deleteUserPhotoInput");
    deleteUserPhotoInput.val('1');
    deleteUserPhotoInput.parents("form").submit();
});


Craft Commerce Upgrade Stuck My installation of Craft Commerce seems stuck after purchasing the Pro license. Im getting similar errors throughout the site:
Base table or view not found: 1146 Table 'craft_xxx.xxx_commerce_customers' doesn't exist.
I've gone ahead and updated Craft to the latest version. Commerce is still on version 2. Updating it to version 3 via the control panel doesn't work (memory limit) and updating via the console yield multiple errors:
Applying new migrations ... error: The command "'/xxx/craft' 'migrate/all' '--no-backup' '--no-content'" failed.
> create table {{%commerce_lineitemstatuses}} ...Exception: SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'xxx_commerce_lineitemstatuses' already exists
Not even sure if I need to update things.. Just hoping to get the site up and running and back into development.. :) I can restore the database and leave the files in place for the recent Craft and old 2.2.22 Commerce and try to upgrade again? Would that work?
Any advice?

While I’m not sure exactly what caused the issue after my client purchased the Craft Commerce Pro license, it was eventually fixed by restoring the database, upgrading Craft and Craft Pro to the current versions on my local machine, pushing those changes to the dev server, and allowing the upgrade scripts to run in full on the dev server. Thanks to @Brad for pointing me in the right direction.


Using a Redirect plugin in conjuction with a wildcard route I have Craft set up to serve a single page Vue App (vue-cli) for all routes it can't match in the sections.

return [
  '<url:(?!api).*>' => ['template' => 'index'],
];

This works perfectly.

However, I was hoping I could also use a Redirect manager plugin like Retour, Redirect Manager or Sprout Redirects.

I tried them all but they only take effect when I disable the routing rule.

How could I have both working together?

I ended up making a 404 template (which in atuality is the SPA index file)

This causes the Craft redirects to take effect, and have the SPA as a fallback route.

This means in Production i don't need any such route. For development purposes i do, so i made a conditional route file (to avoid the debug 404 of Craft):

 if(getenv('ENVIRONMENT') === 'dev') {
   return [
     '<url:(?!api).*>' => ['template' => '404']
   ];
 } else {
   return [];
 }


How to determine if there are events in a calendar? I need to write a conditional that determines if events actually exist in a calendar. I only want to display an option in the the select dropdown IF the calendar has events:

{% set calendars = craft.calendar.calendars({
    limit: 100,
    order: "name",
    sort: "asc"
}) %}

{% set events = craft.calendar.events({
    calendarId: calendar.id
}) %}

{% for calendar in calendars %}

    {# determine what the URL should look like based on the current URL structure #}

    {% if segment1 == '' %}
        {% set urlPart = "month/calendar/" ~ calendar.handle ~ "/" ~ month.date.format('Y/m') ~ "#1" %}
    {% elseif segment3 is not empty and segment4 is not empty %}
        {% set urlPart = "month/calendar/" ~ calendar.handle ~ "/" ~ segment4 ~ "/" ~ segment5 ~ "#2" %}
    {% else %}
        {% set urlPart = "month/calendar/" ~ calendar.handle ~ "/" ~ segment2 ~ "/" ~ segment3 ~ "#3" %}
    {% endif %}

    {# I need a conditional here that outputs an option only IF there are events in the calendar #}

    {% if events %}
        <option value="{{ siteUrl }}cal/{{ urlPart }}"{% if segment3 == calendar.handle %} selected="selected"{% endif %}>
            {{ calendar.name }} - {{ calendar.event.occurrenceCount }}
        </option>
    {% endif %}

{% endfor %}

UPDATE: I expanded this out so you can see everything. Unfortunately, this is still outputting all calendars even if the calendar has no events.

Looking at the docs you can search for events for a certain calander by including the id or the handle in your query.

{% set calendars = craft.calendar.calendars({
    limit: 100,
    order: "name",
    sort: "asc"
}) %}

{% for calendar in calendars %}
    {% set events = craft.calendar.events({
        calendarId: calendar.id
    }) %}

    {% if events|length %}
        // there are events
    {% else %}
        // calendar has no events
    {% endif %}
{% endif %}


Invalid verification code. Please login or reset your password I am sending the set Password URL to a user to set their password after ADMIN create a user in CP.

I am using craft()->users->getPasswordResetUrl($user) to generate the URL for set password which is look like https://<my domain>/actions/users/setpassword?code=8MHKqfmt6Te%5C_dyuCouL4PMaT%7EE%7EV9jNO&id=8bf376ca-e260-44b9-9ad2-0cc623fe4c4c However, I got intermittent user report they get "Oops! Invalid verification code. Please login or reset your password." message pop up after click the link.

In general.php, I have 'verificationCodeDuration' => 'P7D' to make sure the code could last for 7 days.

Does anyone has idea how to verify the code in DB? Looks the verficationCode column in DB is encrypted. Does anyone know how to solve that issue? Thanks

If it's just some users, I've seen some email clients split the link with a newline and when users click it, they don't get the full token in the URL producing an invalid one when Craft tries to verify it.

In those cases, it's recommended that the user manually copy and paste the full URL instead of clicking on it.


frontend form action: save as draft or publish in my frontend entry form I have a "save as draft" submit button.
The current action for this form is the following, which saves the entry submitted through the form as a draft (status: disabled):

<input type="hidden" name="action" value="entryRevisions/saveDraft">

Next to the "save as draft" button I would like to have a "publish" button. If the user clicks on it the entry should be submitted as "status: live". If the user clicks on "save as draft" it should be submitted as "status: disabled". Any idea how to do this?

I believe you're looking for entryRevisions/publishDraft:

<input type="hidden" name="action" value="entryRevisions/publishDraft">

You can see the specific inputs it is looking for here: https://github.com/craftcms/cms/tree/master-v2/src/controllers/EntryRevisionsController.php#L188


specifying section id manually while saving section Is is possible to set the "section id" manually by using

Craft::$app->sections->saveSection($section);?

Can we specify the id of a section in an $section array ?

No you can't. Craft will throw an exception when you insert an id that does not exist into the form. Is there a certain reason for your question? Maybe we could provide help on that.


Multiple variants as "one product" Having a really difficult times with variants.

Classic t-shirt example: The t-shirt comes in red and blue, where each color has 4 sizes. That means I create 4 variants for red, and the same for blue, thus the product "T-shirt A" contains 8 variants.

Each variant has their own stock level, differing prices, image etc.

For size I created a dropdown field and attached to the variants ("Small, Medium, Large" etc).

I can output all variants at the same time on the page, thus allowing the user to select which one they want, but it's not very slick.

How can I make this look like a single product to the user, and simply have a dropdown for Size and Color? When the user selects something in the dropdown, the size and color would update on the page. More importantly, Craft also has to check the color/size combo to see if it's in stock, and reflect that on the page as well.

In Expresso Store (EE) this was easily done with "modifiers", but I'm sure it's even easier in Craft, I just can't wrap my head around it without some help.

Commerce makes no assumptions about, but also provides not real support for, the front end of your store (other than some simple example templates).

It's up to you to build the UI you're looking for - be it a table of variants, or some sort of multi/select type system.  You simply retrieve the product & variants (checking availability as you do) - and then in your twig code build the UI you want.  And if you want dynamic updates of pictures etc, without page reloads, you'll use JS to achieve this.

Super flexible, and quite deliberately built this way to allow complete freedom in content presentation, like Craft itself, but definitely a little less 'for free out of the box' than with some systems.


Search then loop through files that were uploaded via FTP Is it possible to search a server folder containing image and video files that were previously uploaded via ftp and then loop through those files in the entry template?

Each entry has a unique Log ID number field which is also part of the image or video filename.

Example:

Log ID: 12345
Image filename: 12345-[8374]-img-01.jpg
Image filename: 12345-[8374]-img-02.jpg
Video filename: 12345-[8374]-vid-01.mp4
etc...

Conceptually on the template page...

Grab the entry LogID field (ex. "12345")
Search the media server folder for all filenames that begin with the LogID
Display all of the found images and videos

I found this question which is very similar but I don't have the skills to write a plugin.

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


Date picker field type - quickly select year? I need a "date of birth" field. Out of the box, the date picker only allows moving left/right by month, which doesn't work for selecting years.

Is there a way to configure the date picker that Craft uses? Or is there a better way to make a date of birth chooser?

Thanks!

Using carlcs's idea, I put three LJ Dynamic Dropdowns in a SuperTable, here's the code for each dropdown (day, month, year):

{% for day in 1..31 %}
    { "value": "{{ day }}", "label": "{{ day }}" }
    {% if not loop.last %},{% endif %}
{% endfor %}

{% for month in 1..12 %}
    { "value": "{{ month }}", "label": "{{ month }}" }
    {% if not loop.last %},{% endif %}
{% endfor %}

{% set maxYear = now|date_modify('-15 years')|date('Y') %}
{% for year in maxYear..1925 %}
    { "value": "{{ year }}", "label": "{{ year }}" }
    {% if not loop.last %},{% endif %}
{% endfor %}

Then I added a Preparse field that joins these three dropdowns into a date string on each save (I have this under a User, so adapt to Entry/Asset/etc. if you need to).

{% spaceless %}
{% if user.userDateOfBirth | length %}

    {% set dateString = user.userDateOfBirth[0].year ~ '-' ~ user.userDateOfBirth[0].month ~ '-' ~ user.userDateOfBirth[0].day %}
    {{ dateString }}

{% endif  %}
{% endspaceless %}

To calculate age in my template, I use this little snippet (date("2015-07-06") will return a DateTime object so we can use the diff function on it).

{% set ageString = date(dateString).diff(now).format('%y') %}


Random Field Entries I am working on a site for a client who posts many jobs for chefs.

A lot of the jobs are essentially similar, so writing the job postings is something I am trying to simplify.

I can write a series of statements that will serve up similar job descriptions, with pre-written statements that then use |replace to integrate other field data.

So an example statement:

We cook %jobFoodType% to %jobRatingStars%.

Would render as:

'We cook Pub food to a 3 star rating.'

I can write many of these type of statements which can either be selected from a drop down, but I'd like to go a step further and have the drop down when entering a new entry, to be randomly selected from the list of options.

So what I'm asking for, is there a way Craft can randomly pre-populate a field, with a set of predefined statements.

I've had a look at Randomm plugin, which while useful, doesn't let me pre-populate from a predefined set of statements like sentences.

The alternative is to use Randomm to create a random number I use to pick a statement that is in the template, but for obvious reasons, I'd prefer the statements to be driven from Craft.

Any help / thoughts much appreciated. Thank you.

I think I'm following and it sounds like the job for a plugin with a custom field type.

In your example, since you want to use a Dropdown field, then your plugin's field type could extend Craft's default Dropdown field type.

When populating the field type's default values (from your pre-defined statements), you could then randomly select which ones are selected on new entries).


How can I clone a specific Site in Craft, not the default? I have many sites in Craft and I group them by language. For example, German has Germany and Austria sites in them. Spanish has Spain, Mexico and Colombia.

The sections are set to propagate entries across sites.

When we need to create a new site, the entries from the others are created, because of the propagation, BUT they are created from the default English site. So if we create a site in say the Spanish group, it does not create the entries from the other Spanish content, but it creates it from the default site which is in the English group.

How can we create a site and have it created from the group we add it into?

Thanks

I've come across this issue and imagine there will be a better solution in the future, but for now you can change your default site to the one you want to duplicate.


EVENT_AFTER_CREATE_SUBSCRIPTION can someone confirm this means successful purchase? Regarding Event: EVENT_AFTER_CREATE_SUBSCRIPTION
https://docs.craftcms.com/commerce/api/v2/craft-commerce-services-subscriptions.html#events

The document states "The event that is triggered after a subscription is created. Plugins can get notified after a subscription is created."

Using the commerce 2 as an example:

I just need an expert to confirm that a subscription is created or EVENT_AFTER_CREATE_SUBSCRIPTION has executed only when a user has successfully made payment to a subscription.

I've looked into this in more detail now, and whilst it used to be the case that EVENT_AFTER_CREATE_SUBSCRIPTION only worked for successful payments, it's now (post Commerce 2.2.0), no longer the case due to the fact that a subscription can get created in a "Suspended" status, which still triggers that event (https://github.com/craftcms/commerce/issues/1105).

I'm still using that event, but in Commerce 2.2.7 (and beyond unless they change it again!), you'll need to make an additional check inside your code to make sure the subscription is not Suspended.

Event::on(
    Subscriptions::class,
    Subscriptions::EVENT_AFTER_CREATE_SUBSCRIPTION,
    function(SubscriptionEvent $e) {

        // --------------------------------------------
        // BAIL OUT on Suspended subs!
        // --------------------------------------------

        if ($e->subscription->isSuspended){
            return;
        }

        // --------------------------------------------
        // Continue...
        // --------------------------------------------

        ...
    }
);


Plugin function throwing error for missing argument I'm trying to extend a plugin to allow for a limit to be added to the database call but it's throwing an error:

  Missing argument 1 for Craft\Curate_UsersContentService::getRank(),
  called

The services file has a function in it called getRank() and I've added a $count variable to it getRank($count). My twig template then calls it with the following code:

{% set count = 10 %}
{% set rank = craft.curate.getRank(count) %}

But the above error is thrown. What an I missing?

Any clues appreciated.

Ok so worked this out whilst working on another plugin. I had to add a variable to the CurateVariable file in order for the template to be able to use the function. Problem solved.


How can I display search "excerpts" from multiple sections? How do I create search result page "excerpts" when there are multiple sections/fields that need to be represented?

There is no way at present to delegate a field as the search excerpt field in Craft, so it needs to be handled by the search results template. It is possible to use conditionals but this can bloat the template, especially when there are multiple sections and each section outputs different fields in different ways, so I prefer to create dedicated search excerpt templates and include them in the search results template as follows:

{% include ['_search-excerpts/' ~ entry.section.handle, '_search-excerpts/default'] %}

The above code will render the section's dedicated search excerpt template if it exists in a folder called _search-excerpts, otherwise it will render the default search excerpt template which can contain for example:

{{ entry.title }}

The resulting folder structure would then look like this:

_search-excerpts/default.html
_search-excerpts/sectionA.html
_search-excerpts/sectionB.html
_search-excerpts/sectionC.html


Sprout reports timing out on thousands of records I have sprout reports (twig template) exporting tens of thousands of records. Problem is that its timing out. I appreciate that this is expected and my only likely option is to up the server spec.
Is there anything i can do to optimise the report itself? e.g, through tasks where it exports the report over a period of time rather than all in one go?

As you suspected, Sprout Reports is not designed to handle large quantities of data if it's more than your server can handle. As for how many records you could export, it really just depends on how impressive your query is and how much your server can handle.

We could potentially consider adding support for batching large exports. I've created a ticket if you'd like to add your vote for it: Add support for batch exporting large data sets

For now, if you plan to do this on a regular basis you may want to invest in writing a script that makes this a bit easier to do or reach out and contract us to prioritize adding support for this feature.

Within the scope of optimizing the existing queries in your Twig template reports, you could potentially use techniques like:

Eager Loading.
Saving related data ahead of time using a field like the Preparse Field which could potentially reduce the need for complex joins when performing the actual query.
Advanced Twig query techniques (I don't know where these are documented but Brandon mentioned them in his slides here).
Create custom variables or twig functions in your own custom plugins to help optimize how the queries are actually being handled.

Outside of optimizing the query, you could add date range (or some other) settings that lets you give the user control over reducing the size of the full query. There is an example of creating a date range field in the example templates provided in the plugin.


User Registration - Keep as inactive until verified by admin I have set up a public registration form simply using the User registration form: https://craftcms.com/docs/templating/user-registration-form

Is there a way to set it so that when users register they need to be activated by an admin account?

Currently when they register they get an email to verify email address and when they do they get activated.
If I turn off verify email addresses in user settings they simple get activated automatically.

Some sort of workaround

You can make a register user group with no permissions.
Than add another group with the permissions you want.

After registration, the admin can put a new user to the new group.


How to update front end Craft new row - stuck on JavaScript I'm building out a front end entry form with a Natrix and everything is coming along fine. However when users create a new row each new row needs to be unique in order to be saved. This is where I'm stuck.

Simplified HTML:

    block id: new_0

    <input type="text" name="fields[staffProfiles][new_0][fields][employeeName]" value="" placeholder="Full Name">

    <input type="text" name="fields[staffProfiles][new_0][fields][jobTitle]" value=""  placeholder="Job Title">

JS:

var blocknum = 0;

// add a new person
$('#addPerson').click(function(e){
    e.preventDefault();
    console.log('clicked addPerson');

    //iterate blocknumber
    blocknum = blocknum+= 1;
    console.log('blocknum is ' + blocknum);

    var newPerson = "

";
    $('.newBlock').append(newPerson);
    $('.newBlock .newperson:last-child').load('/store/newperson');

    // replace all instances of new_0 with new1, new2 etc.. as rows added
    // this line doesn't do anything, why?
    $('.newBlock .newperson:last-child').replace('new_0','new' + blocknum);

})

console.log('blocknum is ' + blocknum); is showing that the blocknum is increasing with each row. the Replace in the last line of javascript is just not doing anything.

The new person row gets added via ajax correctly but each time it's added [new_0] needs to be unique, but nothing I'm trying is working.

You can get the number of rows you already have from the DOM, then use that to determine how many you'll have after you add a new one.

$('#addPerson').click(function(e){
  e.preventDefault();
  console.log('clicked addPerson');

  var newPerson = "

";
  $('.newBlock').append(newPerson);
  $('.newBlock .newperson:last-child').load('/store/newperson');

  var blocknum = $('.newBlock .newperson').length;
  $('.newBlock .newperson:last-child').replace('new_0','new' + blocknum);
});

Also note that in your example you were replacing using $blocknum, but you had defined it to be blocknum without the $. You've already fixed this :)

Hope this works out!


Possible have matrix rows collapsed by default in the Control Panel? Is it possible to have all Matrix rows in the Control Panel entry be in the collapsed state by default?

Thanks.
Lori

Inject this piece of JS in your CP and they will always be closed by default:

$('.matrixblock').each(function() {
    $(this).addClass('collapsed');
    Craft.MatrixInput.rememberCollapsedBlockId($(this).data('id'));
});

Here's an example plugin that will inject it in the CP: https://gist.github.com/boboldehampsink/6bb9e5296977a99c39b1


Is it possible to run Craft CMS with putenv() function disabled? I’m using shared hosting which supports several CMS like Wordpress, Jumla, etc. In phpinfo there is putenv in disable_functions. Craft CMS needs this function to load variables from .env file. I can acces all varibales at least from $_ENV[].

Is there a way how I can install and use Craft CMS in this environment or is putenv(), getenv() must have?

Thanks a lot for help

DotEnv only calls putenv if it sees the function is available since version 2.4.0, so make sure you're running at least that: https://github.com/vlucas/phpdotenv/commit/58633a061610ffd731d7fbbc8f7f009d14b2e4cf

Even then, I'm pretty sure other Craft dependencies (like Composer) will still require putenv support.


onBeforeSaveUser vs onSaveUser I'm trying to make a very basic plugin that will send an email alert to a User if an Admin changes their User Group.

I thought I could use the onBeforeSaveUser to get the User's current User Group, and then use the onSaveUser event to compare that with the Event's User Group - and then if they differ, do the mail sending.

It doesn't work, and I don't know why. Both events always get the same value for the User Group. What am I not understanding correctly?

private $existingGroups = NULL;

public function init()
{
    craft()->on('users.onBeforeSaveUser', function(Event $event) {
        $eventUser = $event->params['user']; // get the user we are editing

        $user = craft()->users->getUserById($eventUser->id); // get that user's existing information, before we edit it

        $this->existingGroups = $user->getGroups(); // store the groups the User belongs to
        GroupNotificationPlugin::log("existingGroup: " . $this->existingGroups[0]->name, LogLevel::Info);
    });

    craft()->on('users.onSaveUser', function(Event $event) {
        $user = $event->params['user']; // get the user we are editing

        GroupNotificationPlugin::log("Was: " . $this->existingGroups[0]->name, LogLevel::Info);
        GroupNotificationPlugin::log("Now: " . $user->getGroups()[0]->name, LogLevel::Info);

        if($this->existingGroups[0]->name != $user->getGroups()[0]->name){
            GroupNotificationPlugin::log("Changing group", LogLevel::Info);
        }
    });
}

Was: XXX and Now: XXX are always reporting the same, even when I know that I have changed the User Group (unchecking the old one, checking a new one, saving).

The problem is that both onSaveUser and onBeforeSaveUser get fired from UsersService->saveUser() and user group assignment happens in the UsersController->actionSaveUser() after UsersService->saveUser() has already been called.

You should probably be using onBeforeAssignUserToGroups and onAssignUserToGroups instead.


Craft on Heroku is not logging. How can I make it start? I don't have any logs appearing in craft/storage/runtime/logs (in fact I don't have anything at all in craft/storage/runtime.  I'm running Craft on Heroku.  I've tried setting post-install scripts in the composer.json file to run

chmod -R 774 craft/storage

but it doesn't change the permissions (they remain at 700).  We run Papertrail to collect logs from the dynos, but these only seem to include web requests - no application logging.  I've tried enabling devMode, but it makes no difference.

I'm trying to debug some issues we have with the application occasionally falling over, but without access to logs it's impossible - is there any way to make Craft start logging?  Just logging to stdout would be fine, as Papertrail would collect the logs. I can't find any configuration options, maybe I've missed them?

There is a plugin that redirects all of Craft log output to stderr that works on Heroku and Fortrabbit.

https://github.com/ostark/craft-stderr-logger


Custom Asset Source Types - not possible I would love to extend Craft with a custom AssetSourceType. However it looks like components of type 'assetSource' are not extensible (enableForPlugins = false).

Is there a way to do this?
Or can I simply swap core services in the common.php without hacking the core?

My goal is to provide a 'S3CompatAssetSourceType' - the main difference to the S3AssetSourceType is the API endpoint.

Thanks.

Custom Asset sources are not possible in Craft 2 without some core hacking.

However totally doable in Craft 3 (even in the dev preview).  There is an example of how to pull it off here.


Show a list of recently used tags only from the current locale I'm having trouble outputting a list of tags that only includes tags from the current locale.

Here's the setup:

I have a site with two locales: english and spanish
I have a section with handle newsAndEvents
I have a tag field with handle newsTags on entries in that section that is set to translatable to allow my clients to assign locale-specific tags to the entries
I have an entry in that section created with a published version for each of my locales. In the english version, I've added a tag "Turtles" to the entry. In the spanish version, I've added a tag "Tortugas" to the entry.
On the landing page of my news section, I am displaying a list of recent tags in a sidebar. Here's the code I'm using to do it:

{# grab the entries in the specific locale #}
{% set entries = craft.entries.find({section: 'newsAndEvents', locale: craft.locale}) %}

{# Grab the related tags for those entries #}
{% set tags = craft.tags.relatedTo(entries) %}

{# Build the list #}
{% if tags | length %}

  {% for tag in tags %}

{{ tag.name }}

  {% endfor %}

{% endif %}

The problem is, when I'm looking at the english version of my landing page, I get both "Tortugas" and "Turtles" in the list output by the code above. What I want is to only see the tags on english versions entries on the english landing page; and the tags on spanish versions of entries on the spanish landing page.

Some additional info:

If an entry has only one published version, english for example, any tags I assign to that version do not appear on the spanish landing page, as would be expected.
On my entry detail pages, I'm using similar code to generate a list of tags assigned to the current entry, and the output is what I expect: english versions only show tags assigned to english versions, not to both english and spanish like on the landing page.

What am I missing?

Brandon at P&T was able to fill in the piece I was missing. He said:

To only get tags that were related from a specific locale, you just need to specify that in your relatedTo param:

    {% set tags = craft.tags.relatedTo({
      sourceElement: entries,
      sourceLocale: craft.locale
    }) %}

With the addition of order('dateCreated desc').limit(10) to put some additional constraints on what I was getting back, this solved it for me.


Displaying a list of fields in a form select In a plugin's settings view, I'm looking to show a list of fields to choose from:

{% set fields = craft.fields.getAllFields() %}

{{ forms.selectField({
    label:          'Salary Mapping'|t,
    id:             'broadbeanSalaryMapping',
    name:           'broadbeanSalaryMapping',
    instructions:   'Choose a field in which to store this value.'|t,
    value:          settings.broadbeanSalaryMapping,
    options:        fields,
    errors:         settings.getErrors('broadbeanSalaryMapping')
}) }}

However I get an error:

  Craft\FieldModel and its behaviors do not have a method or closure named "optgroup".

Am I going about this the wrong way?

I've got a solution, though I'd be interested to know if there is a better way of doing it. In the plugin file:

public function getSettingsHtml()
{
    $options = [[
        'label' => 'Please select',
        'value' => ''
    ]];

    foreach (craft()->fields->getAllFields() as $field)
    {
        $options[] = [
            'label' => $field['name'],
            'value' => $field['handle']
        ];
    }

    return craft()->templates->render('broadbean/settings', array(
        'settings' => $this->getSettings(),
        'options' => $options
    ));
}

And then in the settings template:

{{ forms.selectField({
    label:          'Salary Mapping'|t,
    id:             'broadbeanSalaryMapping',
    name:           'broadbeanSalaryMapping',
    instructions:   'Choose a field in which to store this value.'|t,
    value:          settings.broadbeanSalaryMapping,
    options:        options,
    errors:         settings.getErrors('broadbeanSalaryMapping')
}) }}


403 Error on homepage of second language We are trying to setup a second language. We've gone through the steps and created a second website, we defined the base URL as @web/de for the second language (German).

The deeper sections are working fine (e.g. www.url.com/de/kontakt). However we can't get the second homepage to work on the URL www.url.com/de. We get a 403 access denied from nginx. We followed all the steps in the documentation (https://docs.craftcms.com/v3/localization.html), but can't get it to work. I assume we are missing something or forgot to do something.

The homepage is a single. In sections, we have left the URI blank for both, the default english site as well as the german site. The template is the same for both.

As a dev environment, we are using Local by Flywheel on a local workstation.

Here are some screenshots of our configuration:

Site overview:

Did you define the the locale url in your config?

I do it like this:

.env

SITE_URL_DE="@web"
SITE_URL_EN="@web/en"
SITE_URL_FR="@web/fr"
SITE_URL_IT="@web/it"

general.php

// Global settings
  '*' => [
    'siteUrl' => [
        'siteDe' => getenv('SITE_URL_DE'),
        'siteFr' => getenv('SITE_URL_FR'),
        'gsiteEn' => getenv('SITE_URL_EN'),
        'siteIt' => getenv('SITE_URL_IT'),
    ],
  ],

Then you can use those as your base URL's:


Craft 3 - Can't access the craft() in plugin controller I'm making a Craft 3 plugin to read a CSV file and insert the data as Categories.

I used pluginfactory.io to scaffold my plugin.

I can't access craft() in my controller (ImportCsvController.php).

My controller action:

    public function actionDoSomething()
    {
      $categoriesGroups = craft()->categories->getAllGroups();
      return json_encode("hi");
    }

My namespacing:

<?php

namespace workyard\csvtocategoryimporter\controllers;
use workyard\csvtocategoryimporter\Csvtocategoryimporter;
use craft\web\Controller;
use Craft;

The error message:

Call to undefined function workyard\csvtocategoryimporter\controllers\craft()

Any ideas why I can't access craft(). Do I have to "use" something in the namespace section?

craft() is gone in Craft 3; instead you will be accessing Craft::$app-> for most things. I'd suggest generating your Craft 3 plugin scaffolding at pluginfactory.io, and if you leave code comments on, it'll give you some hints on how to do stuff like this.

This article might also be helpful to you: So You Wanna Make a Craft 3 Plugin?


Can slug and title changes be propagated to multiple sites? I'm noticing that if I change the title or the slug of an entry after creation, that change isn't propagated to my other Craft sites.  Is there a way to propagate title and slug like other fields?

At the moment I believe this can only be achieved with the site-sync plugin: https://github.com/timkelty/craftcms-site-sync


Reset admin account password using command line interface Can I reset admin password using console CLI interface? Didn't see anything like that when I run the craft file directly and it displayed list of commands.

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

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

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

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


Sort / Order Entries on select or button click I have a page on my website were I display alot of entries. Now I want those entries to be sorted by Date, Title etc. I know how to change that hard coded but I want to make it dynamic with a <select>. I guess I need to use Ajax for this but after a long search I still cant figure it out.

The Select

        <select>
            <option value="{% set order = "postDate asc" %}">New - Old</option>
            <option value="{% set order = "postDate desc" %}">Old - New</option>
            <option value="{% set order = "title asc" %}">A-Z</option>
            <option value="{% set order = "title desc" %}">Z-A</option>
        </select>

The loop

        {% set counter = 0 %}
        {% for entry in craft.entries.section('tips').order('{{ order }}') %}
            {% set counter = counter + 1 %}
            {% include 'includes/tip-blocks' %}
        {% endfor %}

To make the question short.

Sort entries dynamicly through a select form. Prefer not to reload the page but, it's oke if it does.

Okay so you can either do this through ajax or through a page reload, a page reload is going to be much easier, but you can get it to work without reloading the page...

Reloading the page

You can basically make it so that when a user selects an option, use jQuery to redirect to the current page and append the <option> value to append as a query string, so your template could look like this:

<select id="sortQuery">
 <option value="postDate asc">New - Old</option>
 <option value="postDate desc">Old - New</option>
 <option value="title asc">A-Z</option>
 <option value="title desc">Z-A</option>
</select>

Then, you can do this in your template:

{% set orderJs %}
  $(function(){

    $('#sortQuery').on("change", function(e){

     // Get the value from the select
     var filter = $(this).val();

     // We can use twig because we are setting this in template, if you extracted this to its own file, you would need a different means to output the page url
     document.location.href = '{{ craft.request.getUrl() }}?order=' + filter;

   });

  });
{% endset %}

{# let craft include the script to the end of our template #}
{% includeJs orderJs %}

Then, in your template file your code could be:

{% set counter = 0 %}

{# Either get the order from the query or use a default #}
{% set order = craft.request.getParam('order', 'title asc')  %}

{% for entry in craft.entries.section('tips').order(order) %}
  {% set counter = counter + 1 %}
  {% include 'includes/tip-blocks' %}
{% endfor %}

This should then reload the request with the query string, craft will see it and update the response accordingly. I must stress this is untested, but it should work...

Without reloading the page

This gets a little more complex and would involve more jQuery/Javascript than craft so I won't go into too much detail about it.

The steps are pretty much the same as above, except within the script tags (where you listen for a select change) you would make an ajax request to either a html template (which contains the sorted results) or even using the ElementApi plugin to return json (from a template) which you can then iterate over in jQuery and then update your DOM accordingly.

I hope this helps get you on track!


Craft Commerce - How To differentiate between Shipping and Billing Addresses? Is there any method to differentiate between a shipping and billing address in Commerce once a customer has gone through a checkout? I ask because if they come back to their account and want to review their attached addresses and edit them, we want to be able to display them as a Shipping Address and a Billing Address. But from the docs, it appears you can only loop through all addresses with no way to really differentiate them beyond their ID.

This is a pretty common scenario in B2B stores where there may be different shipping addresses for different outlets but one billing address for the head office.

Not simple at the moment. This is because a single address could be used for both shipping and billing on an order during checkout.

You could subvert an existing address field you don't utilize (like attention or title) to store their preference, but that's pretty hacky.

If the user is logged in you have access to their last used shipping and billing addresses with:

{{ craft.commerce.customer.lastUsedBillingAddress ?? '' }}
{{ craft.commerce.customer.lastUsedshippingAddress ?? '' }}

Do you think an address.usedAs field would be useful? It would likely store something like: billing, shipping, or both. Thoughts?


Is it possible to download an asset from an entries tab I was wondering if there was a plugin that would give my client the ability to download an asset – in this case a submitted resume – when viewing an entry in the backend.

I'm pretty sure there isn't currently a plugin which makes that possible (complete list is here), but I'd imagine it's possible to build one.

The trick would be to set it up as a Field Type. Then your field type would have to dynamically figure out what file is supposed to be downloaded, and provide a button for your user to download it.


Deciding between multiple products and variants I'm trying out Craft Commerce for a jewellery website and I'm stuck between creating different products for each material (silver, gold and platinum) or using variants.

Take rings for example. They're available in all three materials and a number of sizes.

By creating a separate product for each material:

Plain band (Silver)
Plain band (Gold)
Plain band (Platinum)

this gives me the advantage of a unique URL for each colour, and I only have to manage one variant (the size) for each product.

It would also make it easier to implement an "Also available in" where the site admin can link to the other colour products in a relationship field (as I understand it it's not possible to link to variants yet).

Am I missing an advantage of having only one product (Plain band) and variants for both the colour and the size?

Thanks in advance,

Tom

Really it largely comes down to data/content concerns.  E.g. using one product allows you to keep all the data that is shared by those products together, and is very DRY...and changes (be it to content, pricing, shipping etc) - only need to me made in one place, versus say 3 in your example.

But the lack of linking to variants is a definite disadvantage (one expects that will come in due course, but for now..)

If the cost of the gain (one place to edit) is too high, or there isn't much data to worry about, then by all means use 3 products and one level of variants.  It's precisely this flexibility that makes Commerce so....flexible!  (And useful :) )

There's no real right or wrong, and it would be easy to test both approaches - and even put them in front of the final editors for their view.


How do I get rid of "web" in URL? I have been all over the docs page and various other topics across the web on this, and nothing seems to solve it for me. It's probably something obvious, but I am stuck. I recently installed Craft 3 on an Amazon Lightsail LAMP server. My file structure is like this:

/opt/bitnami/apache2/htdocs/ (My root folder)

Inside that root folder, I have this structure:

cms (contains all of the Craft installation files)
web (contains index.php, cpresources,.htaccess)

When I load my site at www.example.com, I arrive at a page that just shows my file structure. Only when I click into the web folder (www.example.com/web), does my initial page of my site load up. I want that page to load up without showing "web" in the URL. I have tried the following things with no success:

Changing the Base URL
Changing my httppd.conf file to point to "web" as the root
Moving all of the files inside the web folder into my root folder (htdocs)

And a few other random things. I really am having a hard time pinpointing this exact issue in any of the documentation. Looking for any advice anybody can offer.

Sounds like you need to move everything up one level...

/opt/bitnami/apache2/cms/ (if you can)
/opt/bitnami/apache2/htdocs/

The web folder can be renamed to htdocs (or anything, really) and it will work normally.

If you can't get above htdocs, you'll want to do it like this...

/opt/bitnami/apache2/htdocs/cms/
/opt/bitnami/apache2/htdocs/index.php
/opt/bitnami/apache2/htdocs/cpresources
/opt/bitnami/apache2/htdocs/.htaccess


How to change the Entry status to enabled from Disabled I have created a page where user creates an entry but its status is disabled. This page then redirects to a page where the user gets to see a preview of his entry. On this preview page there are two publish button when clicked the status of the entry has to be enabled. The code I have used is:

<form method="post" accept-charset="UTF-8">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="entries/saveEntry">
    <input type="hidden" name="redirect" value="/user/thanks/{{slug}}">
    <input type="hidden" name="sectionId" value="4">
    <input type="hidden" name="entryId" value="{{entry.id}}">
    <input type="hidden" name="enabled" value="1">
    <button type="submit" class="btn-save">Publish</button>
</form>

But after submitting the form it reloads the same page. I checked the craft.log, it has the following errors:

2017/06/08 13:17:53 [warning] [application] Craft\ContentModel->dailyPlan failed validation: Daily Plans cannot be blank. ( a matrix field )
2017/06/08 13:17:53 [warning] [application] Craft\ContentModel->banner failed validation: Banner cannot be blank. ( an asset field )
2017/06/08 13:17:53 [warning] [application] Craft\ContentModel->Included failed validation: Included cannot be blank. ( a table field )
2017/06/08 13:17:53 [warning] [application] Craft\ContentModel->Excluded failed validation: Excluded cannot be blank. ( a table field )

Can't I change the status of entry simply with the above form? Do I have to load all the required fields with its value? Well I don't want to do that as it would take lot of extra lines of code and also the execution time will be longer, as there are two publish button on the page.

I think so, if they are required fields. You'd just add them as hidden fields and there wouldn't be any additional database queries because it's already fetched the entry anyway.


Can you run Craft CP on one webserver and serve the front end content on a separate one? Much of my work is for a corporate organisation, and there is some resistance to having the CP of a CMS externally exposed. Is it possible to run the Craft CP on one internal (not available outside the network) webserver, and the front end on a separate webserver in the external DMZ which has its access to the CP turned off? Both would talk to the same database (I can see how this could work for two full versions). This is how we run our homegrown CMS which also stores all assets (CSS, JS, templates, images and PDFs) in the database, so I know I would have to find a solution for that, but I am imaging a CDN would solve that problem. What are the technical and licensing issues that need to be addressed? I want to ditch the homegrown CMSes in use, for Craft.

It isn't just the CP that would only be available inside. I want to make all the end user form data be accessible for view and 'office use' update as well i.e. so the form submissions are managed internally only.

Also, I might want to expose separate Sections as standalone websites (these are small 6-10 page medium term sites for conferences, but sometimes have their own domain. The form submissions would be consolidated). These separate sites would all be on the same external server.

It looks like this question was resolved via some extended sleuthing in the comments above:

Can I disable the control panel?
How can I run the Control Panel from a separate domain?

Overall, it looks like the answer is yes, however some part of the solution lies in settings around the server environment and routing rules outside of Craft.


Multi-site Live Preview not working in Craft 3 In the multi-site Live Preview in admin panel show error in the console.

  Failed to load http://www.example.local/test: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'http://www.example.test' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

Update

This has been implemented for the upcoming Craft 3.1 release.

Currently Live Preview will only work across sub-domains (i.e. site1.domain.com and site2.domain.com), not completely different domains (site1.com and site2.com)
 Here's a guide on how you'd set that up: https://craftcms.com/guides/using-live-preview-across-multiple-subdomains

In order for it to work across completely different domains, https://github.com/craftcms/cms/issues/1521 will need to be implemented.


How to change the message on the homepage More newbie stuff.

Here's my index.html

and here's what Chrome is doing

So, where is it coming from because I obviously don't want that message on the homepage?

that's the content of the default 'Homepage' entry, which you'll find in the Entries section of the control panel. That's what is being inserted with the {{ entry.body }} variable in the index.html template.


Admin panel not working without language code I've migrated a website with CraftCms 2 from local to a pre-production server. Everything is working fine but, I don't know why, I only can go to the admin panel with locale code before /admin. I mean, if I write domain.com/admin, it doesn't work. But if I write domain.com/es/admin it works. And this don't happen in local server, only in pre-production.
I get message "Not Found. The requested URL /admin was not found on this server." Instead of a 404 from my webpage.
It works fine in others projects under craft with the same structure and, as I said, in local server works fine too. In root I have:

assets/
craft/
en/
va/
es/
index.php

Any idea? Thanks.

Solved, I left an .htaccess file in root. It wasn't in local server neither, but It seems it was some config in virtual host or something like that to solve it. Once I find this .htaccess in other craft project, was solved ;)
Don't forget your .htaccess in root!


Implementing SimpleSAML PHP in Craft plugin We have been trying to implement SimpleSAML PHP in a Craft plugin to facilitate a SAML login for one of our sites. The problem we are running into is that we always get the NOSTATE error.

The response that gets logged does seem to be correct and the login does succeed, only the way it gets handled in the ACS callback seems to be wrong. That is the moment we get the NOSTATE error. The ACS code is copied from the default SimpleSAML PHP implementation.

We think it has something to do with the session. Something weird seems also to be going regarding the session id that's generated, SimpleSAML PHP generates a new session id regardless of an existing session from Craft. After debugging we located where the session id was generated and forced this to use the Craft session id. However this doesn't have any effect at all.

We've been debugging a lot but can't seem to figure where the State should be fixed. Does anyone have any clue or any idea how to fix this problem.

We managed to circumvent the issue by using the sql session storage SimpleSAML PHP also provides. Not a real solution but a viable workaround.


Display JavaScript only on the homepage What is the best method to render Javascript on specific page using name instead of id. This is what I found but not sure how to use name instead.

{% if entry.id == 2 %}
{% endif %}

{% if entry.section == homepage %}
    //Content goes here
{% endif %}

You'd typically use the {% includeJs %} or {% includeJsFile %} tags within your page template, to specify your page-specific JavaScript, and then output everything in your layout template by calling {{ getFootHtml() }}.

Here's how your (very basic) page template might look in practice:

{# mypage.twig #}
{% extends '_layout' %}
{% includeJsFile "/assets/js/mypage.js" %}

And here's how your (equally basic) layout template might look:

{# _layout.twig #}
<!doctype html>
<html>
<head></head>
<body>

{# This outputs the JavaScript from mypage.twig #}
{{ getFootHtml() }}
</body>
</html>


localhost and root directory for multiple site installs So I usually have multiple sites inside of my MAMP htdocs folder which I then access through localhost:8888/sitefolder. How would this work for a Craft set up? The only way I got my initial Craft site to work was to point MAMPs document root to the public folder of the Craft site I was working on. But this seems pretty messy if I was to be working on multiple Craft sites at once. Surely I wouldn't need to keep changing my MAMP settings every time I wanted to look at another dev site?

Why not use MAMP Pro to define seperate local url's for your projects? Or use something like Virtual Host X.

This way you can define some made up url like: yourporoject.dev and point that url to the public folder of your project.


entry / asset url integrity check Is there any mechanism in Craft (or a plugin) which protects entries or assets from being deleted, if they are used in an asset / entry field used in an entrytype, global, ...?

Or is there a way to show how many relations an asset or an entry has? (I know some CMSs which show you the amount of "inbound" links to the assets and pages).

Thanks!

I just saw this. Consider this plug-in:
https://github.com/born05/craft-assetusage


Get random entries, excluding an array of entry IDs, where a relational field is not empty I'm trying to pull a set of 3 random entries from a Section. The entries need to have a certain Assets field not empty, and I also have to exclude entries already pulled (these entries are stored in the variable entriesA).

The issue is that with my current query, the ID exclusion doesn't work – i.e. I'm getting back entries found in entriesA.

Here's how the query looks:

{% set entriesB = craft.entries({
    section : 'someSection',
    assetsField : ':notempty:',
    limit : 3,
    order : 'RAND()',
    id : 'and, not ' ~ entriesA.ids()|join(', not ')
}) %}

The problem appears to be the assetsField : ':notempty:' statement – when I remove that, I get no duplicates. When it's included, Craft appears to ignore the id parameter and I get back duplicates.

Anyone know what's up? Is it not possible to query using :notempty: statements and id?

That seems to be a bug / limitation of the :notempty: statement, it's probably adding its own ID criteria in the background and the merge doesn't work as expected. I'd suggest you file a bug report.

In the meantime you could just add the "not empty asset field" criteria making use of the relatedTo parameter as a workaround. See How can I get only those entries with non-empty assets field for example code.


More efficient matrix count method I have some logic in a template where I want to count the number of items that have a lightswitch set to yes, and a radio button set to another value, currently I'm doing this via a series of {% set %} variables for loops and if statments, I just wondered if anyone know of a more efficient method to resolve this issue, or if this is the simplest implementation within Craft.

{% set normalNominations = 0 %}
{% set specialNominations = 0 %}
{% set normalWin = 0 %}
{% set specialWin = 0 %}

{% for items in entry.matrixloop %}
    {% if items.type == "awardBody" %}

    {% elseif items.type == "awardType" %}
        {% if items.oscar %}
            {% if items.awardGained == "Win" %}
                {% set specialWin = specialWin + 1 %}
            {% elseif items.awardGained == "Nomination" %}
                {% set specialNominations = specialNominations + 1 %}
            {% endif %}
        {% else %}
            {% if items.awardGained == "Win" %}
                {% set normalWin = normalWin + 1 %}
            {% elseif items.awardGained == "Nomination" %}
                {% set normalNominations = normalNominations + 1 %}
            {% endif %}
        {% endif %}
    {% endif %}
{% endfor %}

{# Debug Information #}
{#
<p> Special win: {{ specialWin }} </p>
<p> Special Nominations: {{ specialNominations }} </p>

<p> Normal Win: {{ normalWin }} </p>
<p> Normal Nomination: {{ normalNominations }} </p>

{{ entry.matrixloop | length }}

#}

Thanks in advance for your help with this, I'm pretty new to Craft so want to make sure I'm being efficient in my templates and not writing rubbish.

Ta

Dave

I'd say that due to the level of nested that you have going on, this is probably as compact of code as you can get out of the box. From an efficiency standpoint, you are only looping through the loop once, so I can't imagine there being anything more efficient.

If you're wanting to minimize the amount of logic in your template, then you can create a plugin and utilize template variables that would accept the matrix content as a parameter. Logic would be handled with PHP and could return an associative array of properties (specialWin, specialNominations, normalWin, normalNominations). So you'd end up with something like this:

{% set matrixData = craft.myPlugin.myPluginVariableMethod( entry.matrixloop ) %}
{# Debug Information #}
{#
<p> Special win: {{ matrixData.specialWin }} </p>
<p> Special Nominations: {{ matrixData.specialNominations }} </p>

<p> Normal Win: {{ matrixData.normalWin }} </p>
<p> Normal Nomination: {{ matrixData.normalNominations }} </p>

{{ entry.matrixloop | length }}

Personally, I'd go with the plugin route just to keep heavy logic out of the templates. It's nice that you can do that type of logic via twig if you want, but it also muddles things up a bit.


Unable to edit single or structures, channels working fine after update to Craft 3 Working in devMode, when trying to edit an existing single or structure entry, I get an InvalidArgument error

yii\base\InvalidArgumentException: Syntax error. in ...vendor/yiisoft/yii2/helpers/BaseJson.php:133

if (isset($availableErrors[$lastError])) {
    throw new InvalidArgumentException($availableErrors[$lastError], $lastError);
}

I notice in Chrome tools I get a bunch of Craft is not defined errors any ideas?

Was an issue with my Simple.json redactor config

Was

{
    buttons: [bold, italic],
    toolbarFixed: true
}

Needed to be

{
    "buttons": ["bold", "italic"],
    "toolbarFixed": true
}


Using Global Variable as Price for Variant I'm trying to set the price of the item being added to the cart by a global variable, which is a number field. Here's what I have:

craft()->on('commerce_lineItems.onPopulateLineItem', function($event)
{
    $lineItem = $event->params['lineItem'];
    $globalPrices = craft()->globals->getSetByHandle('defaultPrices');
    $itemPrice = var_dump($globalPrices->fontStylePrice);
    $lineItem->price = $itemPrice;

This just results in a $0 price being set, and not the value from the Global Variable. But again, $lineItem->price = 25 works fine. Any suggestions?

Removed the var_dump() from setting the variable as follows, and it works perfectly:

craft()->on('commerce_lineItems.onPopulateLineItem', function($event)
{
    $lineItem = $event->params['lineItem'];
    $globalPrices = craft()->globals->getSetByHandle('defaultPrices');
    $itemPrice = $globalPrices->fontStylePrice;
    $lineItem->price = $itemPrice;


How can I determine if a user is logged in, and who that user is? I'm running some checks to see if there is a user logged in, and if that user is someone specific. When accessing user.isCurrent it's returning 1 when I'm logged in, but returns null when I'm not. Should this be returning 0 or false in that case, or should I be checking {% if user.isCurrent is defined %} ?

To determine if the user is logged in at all, you'll want to use the currentUser variable:

{% if currentUser %}
    Welcome, {{ currentUser.friendlyName }}!
{% endif %}

To determine if the logged in user is a specific user, then simply compare against their username:

{% if currentUser and currentUser.username is 'johndoe' %}
    Hey Johnny Boy!
{% endif %}

The isCurrent method is useful when targeting a more generic UserModel (where you don't know if the user would be the current user).

{% for user in craft.users %}
    {% if user.isCurrent %}
        {{ user.friendlyName }} is you!
    {% else %}
        {{ user.friendlyName }} is someone else.
    {% endif %}
{% endfor %}


Order entries by custom time field I've got an events listings which works pretty well and there is a:

Custom Date field, eventEnd (just date)
Custom Start Time, eventStart (just time)
Custom End Time, eventEnd (just time)

I can list these entries so we list by date then time by using:

{% for entry in craft.entries.section('events').order('eventDate', 'eventStart').find() %}

but eventStart is ignored altogether, even when I would use:

{% for entry in craft.entries.section('events').order('eventStart').find() %}

I would expect:

Event 1: 14:00
Event 2: 15:00
Event 3: 16:00

but instead get something more random based I think on post date.

Suggestions welcome thank you!

UPDATE:

my biggest issue is actually being able to list by eventStart at all. Just using {{ eventStart }} reveals the current date. But if I try to boil down to just the hour, it's not a recognised way of ordering (even though it's just a set of numbers?)

So, I'm not sure where to head with this. I'm sure that if my start time was bundled in with the main date, all would be fine, but it makes the system a bit less obvious and flexible.

Here's what I've tried:

{% set completeeventlist = craft.entries.section('events') %}
{% for x in craft.entries(completeeventlist).order('eventDate') %}

    {% set es = x.eventStart|date('H') %}
        {% for entry in craft.entries(x).order(es) %}

{{ entry.id }}{{ es }}

    {% endfor %}

{% endfor %}

Craft always saves a complete DateTime value to the database, even if you only make it set / show the time part of it in the Control Panel.

To ignore the date part (which in this case is set to the day you saved your entry) within the order parameter, you can make use of the time() MySQL function:

{% set entries = craft.entries.section('events').order('eventDate', 'time(eventStart)') %}


Show entries in the Control Panel as a grid, to reorder position I am looking for a way to display entries in a (5er) grid
in the Craft backend (Control Panel) and show only the featured images.

I have a customer who has on her website a gallery, where 5 squares are on
one row. Right now there are around 50 entries, more to come.

All the squares are entries, which have detailed information
on a certain product behind it. The squares are pictures and the customer wants to be able to reorder them, to get the best (aesthetic) combination.

I was thinking of a structure because with this it is easy to order
the entries, but in the Control Panel they are shown as a list.

Is there a way to accomplish this?

I was thinking maybe the Neo plugin might be of help, but I could not try it.

In the Craft backend, I don't think this is possible without (creating) a plugin or module of sorts. Even then, I don't think the element index page is extendable enough to accomplish what you want to accomplish.

Even if you were able to get this done, one way or another, how would you take into account a responsive situation, where more or less than 5 image squares are shown for larger or smaller screens? Would the CP mimic this behaviour?

The only thing I can think of is some sort of table field (Super Table, maybe?), in which you have 5 columns and any number of rows, and every column contains one asset field.


How can you check if a field exists in a section, not by entry? For a plugin, I need to check if a certain field exists in a section. How can i manage that? I'm using the settings section from the plugin, looping through all sections by craft()->sections->getAllSections() and in the template with the following code:

{% for section in sections %}
    {% if section['specificfield'] is not defined %}
        do something
    {% endif %}
{% endfor %}

This doesn't seem to be working. Any ideas on how to check correctly?

The solution is to getEntryTypes() from your section and then access the getFieldLayout() to get to the getFields() (thanks again @Khalwat!). Example:

{% for section in sections %}
    {% if section.getEntryTypes()[0].getFieldLayout().getFields()[0].getField().handle == 'specificfield' %}
        do something
    {% endif %}
{% endfor %}

Notice though that I specifically search for the first occurances, in (most) other cases you should foreach the getEntryTypes() and getFields()


Search order "Score" criteria Leading on from this question by Chris Lewis

I can't seem to find anything on the technicals, but by what criteria "best-match to worst-match" calculated? For example, if I was to have, an entry with the title "Top Trees" then "Top Trees" I would expect to be a "best-match"?

This is a little bit "How do I get my post to the first page of the Craft Search!" I know.

When Craft is determining a matching element’s score, it will loop through each of the search terms, and for each one, loop through each of the element’s attributes, and add the following points to the element’s score:

If the attribute is an exact match of the search term, 100 points will be added
If the attribute contains a full-word match of the search term, 50 points will be added
If the attribute contains a partial match of the search term, 10 points will be added

If the term is part of an “OR” group, then its points will be divided by the total number of terms within that group. So for example, if searching for “gin OR tonic” and an exact match is found within one of the custom fields, rather than getting 100 points, the element would only get 50.

As of today’s 2.2.2582 release, if the attribute is the Title field, then the score will be multiplied by 5. For example, an exact match in the Title field would actually be 500 points, etc.


How can I output the value of a superTable field within a loop? I have a superTable field that I am trying to re-populate on my front-end form.

Everything is working great, I am able to populate a drop-down, but can't seem to find the magic numbers to re-populate a textfield.

<label>{{ field.name }}</label>
<input type="text" name="fields[myField][fields][{{ field.handle }}]" class="form-control" value="{{ entry.myField[0].??? }}">

This works well:

fields[myField][fields][{{ field.handle }}]

But, whatever I enter after that . Example:

value="{{ entry.myField[0].field.handle }}"

I get the error that the model "field doesn't exist". If could make field.handle just be "myField" everything would be great. I can hard-code the field name and it works great. But, I need to be able to access the values within a loop.

Thank you for any suggestions!

EDIT

value="{{ entry.myField[0].field.handle }}"

Is a plainTex field. This is the output I am trying to accomplish.

<input type="text" name="fields[myField][fields][{{ field.handle }}]" value="{{ entry.myField[0].field.handle }}">

The correct markup is:

{{ block[field.handle] }}

The final looks like this:

<input type="text" name="fields[myField][fields][{{ field.handle }}]" value="{{ block[field.handle] }}">


Craft Pro 3.1.33 - Download PDF in admin user profile In Craft 3 Pro i need to download a PDF file that a template form submits to active user profile.

The PDF submits from the front and goes to the admin area under the user account profile.

The problem is that in the user account profile i can see the PDF but cannot download it or even preview it (shows a white thumbnail image with PDF written).

The only way i find to download the pdf is going to the assets section and find it among the other file assets. I do not want this.

Is there a way of adding a download button, or click in the pdf preview to download the pdf, in the user account profile in craft 3 admin backoffice?

Well, the only i way i found to solve this was to made my custom plugin for craft 3 CP.

I build my template scafold here:

https://pluginfactory.io/

Then installed it via composer and started coding to achieve what i want.

Job done.


General Settings > logo in the template I have uploaded a logo in the General Settings, which I understand changes the logo on the login page.

I was wondering if there was anyway to display this same logo in the site's template?

I know I can achieve this by hard-coding the same URL (but I presume if the logo is changed, this URL will change also.) My other solution is to add a field to a global set but that requires changing the logo in 2 places.

If this isn't possible, how can I retrieve the URL in a plugin? (I have a plugin with a few template helper methods.)

Thanks

To fetch the logo:

{{ craft.rebrand.logo.url }}

To check if a logo is uploaded:

{% if craft.rebrand.isLogoUploaded %}


Access environment information in template Is there a way to check what environment craft is running on - ie, dev or not dev - via the template.

For example:

{%if env is 'dev'%}
    hello dev
{% else %}
   hello world
{% endif %}

In Craft 3 you can get the env using the getenv() function:
{% set env = getenv('ENVIRONMENT') %}

{% if env == 'dev' %}
    hello dev
{% else %}
    hello world
{% endif %}

Or via the app’s config service:
{% set env = craft.app.config.env %}

There's a bit more information about the .env file in the docs for Environmental Configuration.