Getting custom user attributes in a service, they return NULL I'm building a service where a few user attributes (category fields) are needed and have to be compared against an entry.

However, when I get the current user and try to load these attributes, they show as NULL. They are filled in at the user's profile, so they shouldn't be NULL.

Below is the code I have used to get try and get the attributes values.

$user = craft()->userSession->getUser();
$user->getContent()->getAttributes()

Some values are filled out, like the custom field for postal code and phone number. However those category fields are all NULL.

Here's some code that should return categories related to a user:

$criteria = craft()->elements->getCriteria(ElementType::Category);
$criteria->relatedTo = craft()->userSession->getUser();

return craft()->elements->findElements($criteria);


Front-end Editing, with Live Preview I am working on an intranet in Craft CMS.
Front-end editing is a very important part of this, and I want to get it perfect.

As it is now, the live preview is perfect for what I want, it provides markup and styling for all field types. If I where to make a custom front-end form for each entry type, including advanced matrix / neo fields etc. the workload would be huge, and I would probably end up doing something similar to what live preview already do.

Therefore I am trying to get live edit to work in front-end, or make it look like it does.

At the moment I just have a link to the CP when pressing "edit" on an entry. And have made use of a hook on afterSave to pick up the front-end url and send the user back to front-end when the entry is saved. This works semi seamless, but I cant figure out a way to trigger the live preview from php, or maybe how to inject some JS when editing an entry after pressing the link in front-end.

So the main question;
Should I keep going with the "trick" to just send the user back and forth between front-end and CP, or should I get the live preview to work front-end? If so, what is the best approach here, I could expose the CP recourses to the front-end, but that sounds like a horrible idea with many concerns.

-- Mathias

Right now the CP Live Preview implementation is very heavily tied to the control panel.  I can't see a easy or clean way to get it to work on a front-end request.

Feel free to make a feature request for it, though.


How to transform German umlauts when creating slugs? First of all, I want to thank you for creating Craft. It's really one of the best content management systems I have ever worked with.

I encountered an issue while working on a multilingual site: German Umlauts are not automatically transliterated (Ä -> Ae) for slugs. In other parts of Craft (e.g. field handles) Umlauts are transliterated automatically.

Personally, I would prefer if this behavior could be controlled by a config variable (e.g. slugExpandUmlauts).

Try enabling the config setting limitAutoSlugsToAscii, that should do what you want.


Adding active class to category link I have a category page displaying only the entries associated with the respective category. I have added a dynamic sub nav for categories using the following:

    {% nav category in craft.categories.group('biographySection') %}

            {{ category.title }}

    {% endnav %}

I need to add an active class on the active link. Can’t figure out the best way to do this. Any help is appreciated.

Below is the code used to display the content from a selected category:

{% set bio = craft.entries.section('biographies').relatedTo(category).find() %}
{% for entry in bio %}
    {{ entry.title }}
{% endfor %}

If you're using the nav on an entries page, this is how you'd do that:

You can check if an ElementCriteriaModel with the following criteria returns anything using the length filter. The ID of the entries must match your current entry's ID and they must be related to the currently looped category.

    {% set activeClass = craft.entries.id(entry.id).relatedTo(category)|length ? 'active' %}
    {{ category.title }}


Public folder confusion I have installed Craft successfully on a local Mac environment using Mamp. I can access the admin area and the default homepage when I go to this address localhost:8888/craft/public/ but I cannot access the site when I go to this address localhost:8888/craft/ Also, when I click on the news link on the default homepage it is a broken link unless I include the public in the URL.

localhost:8888/craft/news/2015/we-just-installed-craft

localhost:8888/craft/public/news/2015/we-just-installed-craft

How do I get around the public folder dilemma?
Thanks in advance.

I'm on a Windows 10 environment with WAMP installed and I had exactly the same problem. Front End failed. Back End worked fine. News links failed. Clicking on website name link from the Localhost screen reveals directory contents. No matter how many times I kept clean installing Craft and tweaking and adding .htaccess files, the problem remained.

I solved the problem in the following way, without the need to add any .htaccess files. It's best to do a complete clean install of Craft.

You'll need the original, untouched, craft and public folders. Apologies if these following points go over what you already know.

Copy the craft and public folders into the wamp/www/sitename folder as normal (or the Mac equivalent)
Remove all the files from the public folder and place them at the base level (i.e. same level as the craft folder)
Delete the public folder.
Rename the root htaccess file to .htaccess
Open up the .htaccess file and add this line

RewriteBase /

after this line

RewriteEngine On
In the root index.php file change line 4 to $craftPath = './craft';
Create your localhost database.
Set up your database connection details within craft/config/db.php.
Via your browser, enter localhost/sitename/index.php/admin/install
Click on the Begin button.
Create your account page, fill out as normal.
When you get to the Setup your site page, complete the Site URL details like this:

http://localhost/sitename

Finish off the install as normal and when your dashboard gets displayed, click on the Website name (top left) to go to the Front End and it will work. Click on the News link and it will work. As will Live Preview. Go to the Localhost page, click on the website name and you will go to your home page instead of having directory details displayed. Finally, if you upload this whole website to your live site it will still work.

Hope this helps someone.

As a slight caveat, I have only been testing Craft for a couple of days and installing it is about as far as I have got to at the moment. So if I've broken Craft no-no's like 'never delete the public folder, then I apologise (obviously, it doesn't have to be deleted and just remain empty)


stream_socket_enable_crypto() error when sending email via SMTP I'm using a third-party email service called SendGrid to send email but am coming up with what I think is a server issue with the SSL. A temporary fix is to edit a line similar to this in a PHPMailer example:

$mail->SMTPOptions = array(
    'ssl' => array(
        'verify_peer' => false,
        'verify_peer_name' => false,
        'allow_self_signed' => true
    )
);

But Craft doesn't use anything that resembles that to me.I want to try hacking the core to see if I can get a temporary fix up but can't find where to put it, despite scouring EmailService.php. Can anyone point me to the function where I'd add these details?

Here's the error,  by the way:

stream_socket_enable_crypto(): Peer certificate CN=`#################' did not match expected CN=`smtp.sendgrid.net' (/home/################/craft/app/vendor/phpmailer/phpmailer/class.smtp.php:367

The fix for the specific error was to switch the port number within email settings to 2525 - that took a lot of finding out, but crucially avoids hacking PHPMailer.


Need a way to connect to a webservice I have a lot of data that sits outside of Craft (the data is in MS SQL Server) and I plan on writing a simple .NET Service which will return JSON. I need to display this data but not sure on how to connect to a service using Craft CMS.

Are there any clients (plugins) which will connect to a service get the JSON data and display it?

Craft 2.x includes Guzzle 3 natively, so you could write a Craft plugin that uses it to consume your web service.

There are plenty of examples in the Guzzle 3 docs on how to do that (as well as in Craft itself).

You could also use something like this: https://straightupcraft.com/craft-plugins/guzzle

Which is a wrapper for Craft's Guzzle 3 you can use from a template.


Implement Cloudways CDN with Craft Is there any way or plugin to implement Cloudways CDN with Craft?

There is a CDN plugin called Upper. You could do a feature request on there github.com/ostark/upper/issues . Or look at how they implement the CDNs in their plugins and make your own.


How are changes to the dashboard scoped? I'm working on a Craft project with another developer. We're connected to the same shared database but my dashboard is different than his (I customized mine).

This made us wonder how the custom dashboards are scoped. Are they based on user? Or are they based on a user group and "super admins" have their own individual scope?

Every user has their own unique dashboard. The changes you make to your dashboard affect only your account.

It cannot be shared, and it cannot be preset in any way. It is not related to user groups at all. The only way to change someone else's dashboard is by logging into the control panel as an admin, then finding that user and "Log in as them".

There have been a handful of feature requests regarding pre-setting dashboards, or remotely controlling or locking another user's dashboard... but for the near future, this is simply how dashboards work.


Search using the MX Range Slider plugin I have a super table field (scoreRanges) that has two columns: mx range slider (range) & rich text (summary). Some entries can have multiple rows:

I'm trying search a row in that field that has a range between a certain value. MX range slider saves data ranges to the database text field like 9;20 which is a range from 9 to 20.

Does anyone have an idea of how to search for a row between a certain range? So far I have tried this which returns no results.

{% for range in profile.scoreRanges.range('and', '>=' ~ result.points, '<=' ~ result.points) %}
...
{% endfor %}

On the template side, I have variables like {{ range.range.from }} & {{ range.range.to }} to use.

Update

Currently not ideal. Using a conditional to filter the correct row, but will work now ¯\_(ツ)_/¯

{% for range in profile.scoreRanges %}
    {% if result.points >= range.range.from and result.points <= range.range.to %}

Range: {{ range.range.from }} - {{ range.range.to }}
 Your Score: {{ result.points }}

        {{ range.summary }}
    {% endif %}
{% endfor %}

The way the plugin is currently written, it won't support your initial syntax. i.e. range('and', '>=' ~ result.points, '<=' ~ result.points).  It would need to override BaseFieldType's modifyElementsQuery to support that syntax.

You could slightly improve on your solution by using the MN Break and Continue plugin to at least break out of the for loop once a match is found.


Check if page is Search, use different classes I'm looking for a shorter way of writing this check. If the user visits the search page, apply the 3 column to the search-block, else use the 5 column:

{% set currentPage = 'search' %}
{% if currentPage == "search" %}
   {% for project in pageEntries %}
      {% include '_partials/search-block' with {
         extraClasses: '3col'
         }
      %}
   {% endfor %}
{% else %}
   {% for project in pageEntries %}
      {% include '_partials/search-block' with {
         extraClasses: '5col'
         }
      %}
   {% endfor %}
{% endif %}

{% set class = (currentPage == "search")? '5col' : '3col' %}
{% for project in pageEntries %}
     {% include '_partials/search-block' with {
        extraClasses: class
     } %}
{% endfor %}


Multiple Prices based on User in Craft Commerce This is my first time using Craft Commerce.  I have a client which needs to have multiple prices for a product.  Customers are in one of three price level groups.  Each price level group has a price unique to them as a variant.  How do I get only the one variant for the appropriate price?

Here is what I tried, but returned all the variants for each price level instead of just one.

                <select name="purchasableId">
                    {% set purchasable = craft.commerce.products %}
                    {% for purchasable in product.variants %}
                        <option
                            {% if purchasable.stock <= 0 and purchasable.unlimitedStock == false %}disabled {% endif %}
                            value="{{ purchasable.purchasableId }}">

                                Product Number: {{ product.stockDescription1 }} |
                                Price:

                                {% if currentUser.isInGroup( 'priceLevelOne' ) %}

                                    {% set variant = craft.commerce.variants %}
                                    {% for variant in product.variants %}
                                        {% if variant.priceLevel1 == 1 %}
                                            Product Number: {{ product.stockDescription1 }} |
                                            Price:
                                            {{ variant.price|currency(cart.currency) }}
                                        {% endif %}
                                    {% endfor %}

                                {% elseif currentUser.isInGroup( 'priceLevelTwo' ) %}

                                    {% set variant = craft.commerce.variants %}
                                    {% for variant in product.variants %}
                                        {% if variant.priceLevel1 == 2 %}
                                            Product Number: {{ product.stockDescription1 }} |
                                            Price:
                                            {{ variant.price|currency(cart.currency) }}
                                        {% endif %}
                                    {% endfor %}

                                {% elseif currentUser.isInGroup( 'priceLevelThree' ) %}

                                    {% set variant = craft.commerce.variants %}
                                    {% for variant in product.variants %}
                                        {% if variant.priceLevel1 == 3 %}
                                            Product Number: {{ product.stockDescription1 }} |
                                            Price:
                                            {{ variant.price|currency(cart.currency) }}
                                        {% endif %}
                                    {% endfor %}

                                {% endif %}
                        </option>
                    {% endfor %}
                </select>

User groups are not a FieldType so you can create a category that matches the title of the userGroup or put the actual category as a field on the User and the Variant. Then in your template do something like this:

{% set userGroup = currentUser.userGroup.first() %}

{% set variants = craft.commerce.variants.product(product).relatedTo(userGroup) %}

This would probably be the best way since you aren't reliant on string matching a title to find the correct variants.


Within the CP, how can I filter the listed Entries based on a Lightswitch field value? I tried these kind of searches in the CP search field (on top of the Entry list):

fieldHandle:true / fieldHandle:false
fieldHandle:1 / fieldHandle:0
fieldHandle:* / -fieldHandle:*
fieldHandle:not 1 / fieldHandle:'not 1'
etc.

Unfortunately, none of these returns the expected entries.

Lightswitch fields are a bit of an edge-case in searching because it can only be true/false (in the real boolean sense of true/false) so Craft doesn't explicitly index it in the searchindex table.
That's a bit awkward because even through there is a field setting "use this field's value for the search index" it's the one field where it doesn't apply.
Regardless, this should all be rectified for the upcoming Craft 4 release where we plan to make this possible.


Transform different image if specific id or order I have a masonry type image grid layout and I need to specify a different image transform for just the 2nd and fourth images in this grid.

Does the image ID relate to the order or to the specific image? How could I include a conditional in my code to output the largeIndexHalf image transform for the 2nd and 4th image?

{% set asset = entry.portraits %}
{% if asset | length %}
{% for asset in entry.portraits %}

{% endfor %}
{% endif %}

You could do that like so:

{% for asset in entry.portraits %}
    {% if loop.index == 2 or loop.index == 4 %}
        {% set transform = 'largeIndexHalf' %}
    {% else %}
        {% set transform = 'largeIndex' %}
    {% endif %}

{% endfor %}

or more simply (making use of the containment operator (in) and the ternary operator (? :):

{% for asset in entry.portraits %}
    {% set transform = loop.index in [2, 4] ? 'largeIndexHalf' : 'largeIndex' %}

{% endfor %}


Craft 3 Element API: Query the "parent" entry of a "child" entry with Matrix blocks connected by an 'Entries' field In a Matrix block field of a "page" entry, I'm using an Entries field to manually select a list of "article" entries to the "page" entry.

When I query an "article" entry, is it possible to query its "parent" page entry that's connected using the above method or do I have to use categories?

BTW it'd be appreciated if the solution is written for the Element API plugin or PHP code if possible.

Thanks!

EDIT: edited question to be more accurate by adding the Matrix details.  Also, the correct query would be:

Entry::find()->section('page')->relatedTo([
    'targetElement' => $article,
    'field' => 'articleSections.articles'
])->all();

$page = Entry::find()
    ->relatedTo([
        'targetElement' => $article,
        'field'         => 'articleSections.articles'
    ])
    ->section('page')->all();

Please read the docs about ElementQueries and relations

Note: the Element API Creates an ElementQuery from your criteria property.

criteria => [
    'sectionId' => 4,
    'typeId'    => 1
]

Is the same as

Entry::find()->sectionId(4)->typeId(1)


Craft Commerce cart timing out but allowing order to be processed We had a Stripe order go through recently, where the order value was zero and there were no line items. The client has called the customer to figure out what happened:

The customer added a product to the cart as normal.
They entered their address details.
They reached the payment page and left it there for over an hour.
They returned and went to pay with Stripe, entering their card details and the payment seemingly going through but with a value of £0.00.
They were redirected to the order thank you page and received their order email detailing their purchase of nothing for £0.00.
They then completed the purchase afresh and it went through fine.

It's presumably an issue with the cart timing out. Does anyone know if there is anything I can do about this?

This is likely due to the item going out of stock while they were away from the cart, then when they went to pay, the item had to be removed from the cart, but they should have seen an error message when they tried to pay:

  Something changed with the order before payment, please review your order and submit payment again.

The secondary issue is allowing zero value orders. At the moment, zero value orders are allowed and payment gateways are not even called due to the payment due being zero.

On the client side, you could hide the payment buttons if the order value is zero.

We should introduce an allowPaymentOnZeroValueCarts type config option that stops these orders from coming through if dezired. I will add that to the next release.

I might also be a good idea to put some javascript on the page, that forces a refresh after a timeout.


How do I filter by multiple Smart Map addresses? I have profiles (Users) that can have multiple addresses (currently two Smart Map fields called profileAddress1 and profileAddress2).

I know how to filter by a single address:

{% set results = craft.users({
    group: 'profiles',
    profileAddress1: {
        target: 'Cologne',
        range: 20
    }
}) %}

How would I search across both fields? So if a profile had two addresses – one in Cologne and one in Munich – it should show up in the results in both search cases (Cologne and Munich).

Is that even possible?

You would need to setup two criteria models, one for each Smart Map field, and query for the element IDs. Merge these IDs and have a 3rd criteria model where you pass in the IDs to the id parameter.

See this question for example code:

  Complex logic on a ElementCriteriaModel parameter?

Here's a blog post describing the technique in details:

  Manipulating Craft's ElementCriteriaModel objects with Twig

If you need better performance, have a look at the custom Yii query builder code I posted here:

  How can I query for entries that have one of two Lightswitch fields enabled?


Get a list of countries available for shipping with Ajax in Craft Commerce I need to fetch a list countries available for shipping in Craft Commerce.
The problem is that I use decoupled frontend on Nuxt.js and I need fetch it with Ajax call and not with the twig code.
I tried to call it in a Postman but it returns me a 403 - Forbidden error with message "User is not permitted to perform this action".
I couldn't find something about the way of making request through Ajax in Commerce documentation, can you please tell me what I'm doing wrong here?

You need to provide a CSRF token, alternatively turn it off in your config/general.php file.
Set a token in your twig template:
{% set csrfToken = {
    csrfTokenName: craft.app.config.general.csrfTokenName,
    csrfTokenValue: craft.app.request.csrfToken,
} %}

<script type="text/javascript">
    window.Craft = {{ csrfToken|json_encode|raw }};
</script>

Then include the CSRF token name and value in your post array (data):
data[window.Craft.csrfTokenName] = window.Craft.csrfTokenValue;

Alternatively you can set enableCsrfProtection to false in your general config file.


How to redirect with error messages? If validation fails in plugin, how can I redirect it bank to previous URL with errors?

craft()->urlManager->setRouteVariables(array(
    'errors'    => $errors
));

gives 404

My Controller:

class DB_LogsController extends BaseController
{
    protected $allowAnonymous = true;
    public function actionStoreDances()
    {
        $this->requirePostRequest();
        $f = craft()->request->getPost('logs');
        $dances = new DB_LogsModel();

        $errors = $dances->getAllErrors();
        craft()->urlManager->setRouteVariables(array(
            'errors'    => $errors
        ));
        $redirectUrl = '';
        //$this->redirect('http://db.craft.dev/admin/db/',true);
    }
}

How to redirect with error messages?

Generally speaking, then answer is "you don't".  You redirect on success, but if there is an error (validation or otherwise), you add those to your model, call setRouteVariables and let the request continue as usual.  That will reload the current page and you can pull the errors out of the model from Twig.

You can see the general workflow for this in a controller action in all of Craft's controllers at craft/app/controllers.

class SomeController extends BaseController
{
    public function actionDoSomething()
    {
        $myModel = new MyModel();
        $myModel->myProperty = 1;

        // Validate the model
        if ($myModel->validate())
        {
            // Pass it to the service.
            if (craft()->myService->doSomething($myModel))
            {
                // Success!
                $this->redirectToPostedUrl();
            }
        }

        // Return the model back to the template so the errors can be displayed.
        craft()->urlManager->setRouteVariables(array(
            'model' => $myModel
        ));
    }
}


Unknown error occured? When I install the Craft Commerce plugin on Craft CMS, I found an error "unknown error occurred".  Please tell me about this error and how to fix it. I will be very thankful.

I have a lot of google search on it but nothing useful.

Thanks again.

it is simple ! only edit php.ini file which is in your xampp folder . increase msql connection time and increase cache i.e limit size and that solve.


finding core dumps in public root Am suddenly finding lots of core..xxx files dumped in the root of my site.
In devMode cant see any issues. Assume this is serious issue and memory dump?

Where to start? Logs have loads of stuff but nothing that gives me a clue to this.

Those aren't Craft log files.  I'd suggest contact your host and give them the files so they can look and see what's dumping them and what the root problem is.


Update Commerce Cart using Fetch Hi this is a variation of the question asked here on updating the cart using ajax, instead I'm attempting to use the Fetch API. As a test the form submits properly when submitting in the usual way without using the Fetch request. I've attempted to replicate the synchronous request header that I inspected in the Chrome Network tab but I still get a Bad Request error.

HTML:

<form method="POST" id="addToCartForm">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="commerce/cart/updateCart">
    <input type="hidden" name="redirect" value="/cart">
    <input type="hidden" name="purchasableId" value="{{ product.id }}">
    <input type="number" name="qty">
</form>

JS:

let formElem = document.getElementById('addToCartForm');
let form = new FormData(formElem);
let request = new Request('/', {
  credentials: 'include',
  method: 'post',
  mode: 'same-origin',
  redirect: 'follow',
  headers: new Headers({
    'Content-Type': 'application/x-www-form-urlencoded',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    'X-Requested-With': 'XMLHttpRequest' // so craft detects ajax
  }),
  body: form
});

fetch(request).then((response) => {
  if(response.ok) {
    return response.text();
  }
  throw new Error('Network response was not ok.');
}).then((response) => {
  console.log('Worked:');
  console.log(response);
}).catch((error) => {
  console.log(error);
});

The problem was resolved by changing the headers set:

let form = new FormData(this.form);
let request = new Request('/', {
  credentials: 'include',
  method: 'post',
  mode: 'same-origin',
  redirect: 'follow',
  headers: new Headers({
    'Accept': '*/*',
    'X-Requested-With': 'XMLHttpRequest'
  }),
  body: form
});

Instead of declaring the Content-Type in the request, I set the encoding type on the form itself, this step is optional as the request sets as multipart/form data by default I think.

<form method="post" enctype="multipart/form-data">
..
</form>


Infinite getPrev and getNext? I know how to display every next entry, but is it possible when there is no next entry it displays the first one and if there isn’t a previous display the last entry?

You would need query for these entries using the first and the last method.

{% set criteria = craft.entries.section('blog').order('title asc') %}

{% set prevEntry = entry.getPrev(criteria) ?: criteria.last() %}
{% set nextEntry = entry.getNext(criteria) ?: criteria.first() %}

{{ prevEntry.title }}
{{ nextEntry.title }}


Is it possible to increase the Title character limit? Simple use case: I have a channel that is setup solely to be used in an entries field to relate goals that are used on multiple pages. The goals channel simply has the title field, as the goals themselves are all one sentence statement and need to be easily identifiable by content editors for the site. Unfortunately, one of them is 268 characters, and the Title field has a limit of 255 characters.

So my question is - is there a recommended way to change the character limit for the title field? If it's in the database structure, where is it? (I will continue to dig through the database for this). If it's in config, is there a configuration override to do this so it doesn't get changed back every update, or a plugin?

Thanks!

The title column in the craft_content database table has the column type VARCHAR, which is limited to 255 characters. There's no setting that'll change the column type for you – you can always use a tool like phpMyAdmin or Sequel Prop to change it to TEXT in order to increase the limit and it'll probably work, though it seems like a bit of a risk.

Edit: Brought to my attention by the OP in the comments below that both the actual input field and possibly some validation functionality is also limiting the title field to 255 characters. My revised TLDR answer: Nope, don't bother trying :)

In my opinion, the following would probably be a safer/better way to solve your issue:

Add a PlainText field to your Entry Type (give the handle text or the like). Consider making it multiline, since there's a fair amount of text for each entry.
Pop into the Entry Type's settings (under CP -> Settings -> Sections -> [entry type], and uncheck the Show the Title field checkbox.
In the Title Format field that appears, add something like this:

{{ object.text | length > 252 ? object.text | slice(0, 252) ~ '...' : object.text }}

With the above in place, your content editor(s) will still only have to edit a single field (it'll just be called Text instead of Title), and the contents of the "Text" PlainText field will be copied over to the actual Title field when the entry is saved. For the few entries that have more than 255 characters, the title will be truncated to the first 252 characters, suffixed w/ ... – those 252 characters should probably be enough to identify each entry inside the CP (you might want to add fuzzy searching, btw), and the dots look nicer than just cutting the text off. The text field will contain the full, un-truncated text.

Obviously, in your templates you'll need to use {{ entry.text }} instead of {{ entry.title }} to get the full text.


Set parent nav to active I have a navigation like this:

{% set navi = craft.entries.id('2, 4, 5, 6' ).order('id asc') %}

    {% for entry in navi %}

{{ entry.naviTitel }}

    {% endfor %}

This results in something like:

Home
Projects
About
Contact

Now under Projects (Wich is a Single entry) are entry pages like this:

url/projects/project_entry_1
url/projects/project_entry_2

Now what I'm trying to achieve is that when viewing a project_entry, the nav link "Project" should have the class active which is not the case right now. Is this somehow possible with this navi markup or do I have to write something like this.

I taught about writing a conditional {% if url_segment 2 == project %} but that doesn't work because this would give all links the class active and since I have a multi-language installation segment_2 is not always the single slug.

What is the prettiest way to achieve this?

Thank you.

You need to get all possible translations of your entry slug to do a thorough comparison.

This is only possible with additional DB queries (ElementCriteriaModels) for each of your navigation items and each of your installed locales, if you don't want to hardcode the values into your template.

Because your navigation probably doesn't change that often, I'd do it anyways and simply wrap the whole navigation in {% cache %} tags with a really long invalidation time (it does get updated if anything is changed within the tags though!).

{% cache for 3 years %}
{% for naviItem in navi %}

    {# Get the relevant URL segment #}
    {% set segment = craft.request.segment(1) %}

    {# Get all possible translations of the entry slug #}
    {% set enSlug = craft.entries.id(naviItem.id).locale('en').first().uri %}
    {% set frSlug = craft.entries.id(naviItem.id).locale('fr').first().uri %}
    {% set deSlug = craft.entries.id(naviItem.id).locale('de').first().uri %}

    {# Define a variable `activeClass` if the URL segment matches one of the slug translations #}
    {% if segment == enSlug or segment == frSlug or segment == deSlug %}
        {% set activeClass = ' active' %}
    {% endif %}

        {# If the `activeClass` var is set, add its value to the link's classes #}

            {{ naviItem.naviTitel }}

{% endfor %}
{% endcache %}


Upgrade C2 to C3 Uncaught TypeError involving Dotenv I am just trying to upgrade and get the following error message:

Fatal error: Uncaught TypeError: Argument 1 passed to Dotenv\Dotenv::__construct() must be an instance of Dotenv\Loader, string given called in (…) /html/index.php on line 17 (…)

Which is completely new to me. Never happened before and my setup is pretty standard. Is this a hosting Problem? Can’t make anythiong of it.

Craft version seems to be 3.3.4 according to the name of the zip (Craft-3.3.4.1.zip).

Using a earlier version of Craft (3.3.3) solved the problem. Updating from there was shaky but eventually worked.


Verbb Comments plugin - Can't see comment replies I recently installed Verbbs Comments plugin on my Craft site, which seems all well and good except that I can't toggle the comment replies. ('2 comments' when clicked does nothing)

Everything else works fine but that. I'm currently using the sample CSS and JS which was provided on their website.

I have also tried the AJAX version provided on this page:

https://verbb.io/craft-plugins/comments/docs/feature-tour/example-css-js

Not trying to override anything on this plugin, just want to get the sample up and running.

Also, no error in console.

I remember having to modify the javascript and templates quite extensively to get it working. Take a look at the code and find out what needs fixing. If you're using Bootstrap you can modify the template so that it uses Bootstraps buttons and dropdowns, and that's how I got it working nicely.


Use a custom Element Type without sources? I want to create a custom plugin (element type) that does not allow custom fields. Therefore, when digging through existing element types, do I really need to have the getSources method?

If this is the case, what is the P&T definition of "sources" and are there any base element types that don't use "sources"?

Element Types, Custom Fields, and Sources can work closely together, but how you structure that relationship has a lot of flexibility.

Sources are optional.  They are a convenient way to group and filter Elements, but they vary in the way that they group those Elements – Globals use Global Sets, Categories use Category Groups, Entries use Sections – and if you don't need them, you should be able to just leave them out altogether.

One place, where sources aren't completely non-existent, but where you will see the Craft user interface present an Element Type without any sources is if you restrict an Asset field to a single folder or an Entry Relations field to a single Section.  When you trigger the field modal to select the related Assets or Entries, you will not see any sources in the sidebar, because all the Elements fall into that singular container that you set in the settings.

Building your custom Element without sources would behave in a similar way. Your Element index page and your Element Field Type will expand to full width and your user will just see your content however you wish to present it.

Update

To your question in the comments: What should be an Element Type?

I'm sure this is a much longer discussion, but I will volunteer a vague one sentence answer!:  when the benefits of using the extendable features of Element Types (sources, search, relations, etc.) outweigh the costs of developing more specific custom solutions for your needs.


Unable to update slug in Craft 3 for single enteries I have created some entries for type single but now I am not able to update their slug even I have updated the title

You have to change the URI format in your section for the specific language.

Go to settings -> sections -> your single section, there you'll have a table below and you can insert the URI format you like for every site.


How to set a different URL format for each entry type of a section? Is there any way to set a different url format for each entry type of a section?

I have an entry type "image" on which I will be using the Randomm plugin by Fred Carlsen to generate random strings for the URLs. Something like mysite.com/image/324739483. So I have to set the URL format to image/{customFieldHandle}.

But I also have an entry type "articles" and I'd like to add the actual article name in the URL, like mysite.com/articles/some-article-name.

You can set the URL format to something like this and it should work:

{% if object.type == "image" %}image/{customFieldHandle}{% elseif object.type == "articles" %}articles/{slug}{% endif %}


Query only Tags wich are not connected to a revision I wrote a query like this:
 $query = (new Query())
        ->select('COUNT(elements.id) as count, tags.*')
        ->from('relations')
        ->join('INNER JOIN', 'tags', '{{relations}}.targetId={{tags}}.id')
        ->join('LEFT JOIN', 'content', '{{content}}.elementId={{tags}}.id')
        ->join('LEFT JOIN', 'elements', '{{elements}}.id={{tags}}.id')
        ->where([
            'elements.enabled' => 1,
            'elements.revisionId' => NULL
        ])
        ->groupBy('{{relations}}.targetId')
        ->orderBy('count DESC');

So my intention there is to fetch all tags wich have content and do have revisionId IS NULL.
But it never works. I get just all the relations including these one related to elements with a revisionId not null.
Can someone help me in this issue.
I am completely new to craft and use to the symfony query builder wich is kind of different.

I found the solution and posted it here in another issue related to this problem.
Here is my solution (just the code):
$query = (new Query())
    ->select([
        '{{relations}}.targetId as id',
        'COUNT({{relations.targetId}}) as count',
        '{{content}}.title as title'
    ])
    ->from('relations')
    ->leftJoin('tags', '{{relations}}.targetId={{tags}}.id')
    ->leftJoin('content', '{{content}}.elementId={{tags}}.id')
    ->leftJoin('elements', '{{elements}}.id={{tags}}.id')
    ->leftJoin('elements source', '{{source}}.id={{relations}}.sourceId')
    ->where([
        '{{elements}}.enabled' => 1,
        '{{source}}.enabled' => 1,
        '{{source}}.revisionId' => NULL,
        '{{source}}.draftId' => NULL,
    ])
    ->groupBy('id, title')
    ->orderBy( 'count DESC, title ASC')
;

$query->limit($limit);

if (is_numeric($limit) && !is_null($limit)) {
    $query->limit($limit);
}

$results = $query->all();

foreach ($results as $key => $value) {
    $id = $value['id'];
    $results[$key] = Tag::find()->id($id)->one();
}

return $results;


How to save extra data when I save an entry I am trying to understand if it is possible to do a hook on an entry save without creating a plugin.

This is what I would like to happen:
- In my entry, I have some address fields (street, city, province...).
- I would like to take those info and go grab a lat and long from Google maps and save it with the entry.  The lat and long fields are also available in the entry if people want to fill them or modify them.

I was doing all this in Wordpress with custom post types, but I'm trying to convert it to Craft.

Is it possible or do I have to create a plugin to do it?

I think the short answer is yes, you do need a plugin to listen for events or tie into Craft's hooks.

Luckily if that is all you need to do you can probably get away with writing a plugin that is only the singular plugin class file, you may not need any other plugin classes (models/records/etc).

It seems as if you want to listen for onSaveEntry.


Output Matrix Content from Sibling I need to get Matrix field content from a entries sibling. Essentially, I have a block type called gallery within my project pages, and under the project content on each page, I have a section for Other Recent Projects. I'd like to be able to get the first image from the gallery block of the previous and next siblings and output it in this recent projects section. How can I do that?

Thanks,
J

Something like this might work (obviously, replace the matrixField, assetsField and imageTransform handles with real values):

{# Basic query parameters for your sibling entries #}
{% set siblingCriteria = craft.entries.section(entry.section.handle) %}

{# Creates an array with the next and previous entries, based on the basic query parameters #}
{% set siblingEntries = [entry.getPrev(siblingCriteria), entry.getNext(siblingCriteria)] %}

{# Loop through the next and previous entries
{% for siblingEntry in siblingEntries %}

    {% if siblingEntry %}{# This might be null, if there isn't a next or previous entry #}

        {# Get the first `gallery` block for the entry's Matrix field #}
        {% set galleryBlock = siblingEntry.matrixField.type('gallery').first() %}

        {# Get the first asset in the gallery block's Assets field #}
        {% set galleryImage = galleryBlock ? galleryBlock.assetsField.first() : null %}

        {# Render the image #}
        {% if galleryImage %}

        {% endif %}

    {% endif %}

{% endfor %}


How do I install Craft in shared hosting that doesn't allow index.php in a sub-folder I’ve got a small, low traffic site that I’ve rewritten with Craft and a Bootstrap responsive grid, mainly as a learning exercise. The original site has just a dozen static pages, and is hosted with Fasthosts UK-based shared hosting. My new site, although small, makes extensive use of Craft’s Matrix. I’ve learned a lot and I’m really pleased with it.

I’ve started to install the new site (alongside the old one) and I’ve discovered that Fasthosts shared hosting doesn’t allow the new index.php file to be located inside a ‘public’ sub-folder – it has to be at the root of the htdocs folder. So my first option seems to be to empty the contents of my ‘public’ folder into my htdocs folder, to live alongside the craft folder.

There are stern, but mysterious, warnings about doing this in Craft’s installation documentation: "We recommend that you upload the folder above your web root if possible, which will ensure that no one can access any of its files directly. (Your web root is the folder that your domain name points to.) That’s not a requirement, but do it if you can. For the children.”

Could someone please explain what bad things might happen if I take this first option?

I did a bit of research before I posted this question, and I came across a second option to leave everything in the public folder and to use mod_rewrite code in the .htaccess file to re-route requests for index.php into the public folder.

Lastly, I found a third option of creating an extra index.php file located in the htdocs folder to point to index.php the public folder, with this re-direction code:

<?php
header('Location: http://mydomain.com/public');
exit;
?>

Which of these three options is the best compromise from a security / SEO / performance perspective?

It's not so much that you can't have the index.php file in a subfolder that might be an issue; it is that you can't put the craft folder above your webroot. If you have access to the folder that htdocs is inside, you should try putting the craft folder inside that. It might not be obvious, but there's no reason that the public folder has to be named public. It could be html, htdocs, or whatever. The point is that you're suppose to put the craft folder above this folder.

On many "simple" webhosts, you may not be allowed to do this, and you have to put the craft folder within your public folder. The security risk involved with doing this is, as the warning states, related to your craft folder being directly accessible through a webbrowser. For instance, you're db.php config file would now be "accessible" by going to http://yourdomain.com/craft/config/db.php. As long as your webserver is configured correctly, and there are no security holes to exploit, this doesn't really matter, since the file will be processed as php, and doesn't output anything.

But, in theory, if a malicious user manages to, for instance, crash the php process, he'd see the file as pure text. Or, if he's able to initiate a download of a file inside your public root, he'd be able to get to all your configuration files. But, then again, you might have problems even if the craft folder is outside of your public root.

If you can't put craft outside your public root folder, options 2) and 3) doesn't really help, they just introduce more problems. Just put the files in your public folder, and the craft folder, inside your htdocs folder, and reconfigure the path to craft in index.php to:

$craftPath = './craft';

Then, make sure that inside your craft folder the .htaccess file that comes with Craft is still there. It's suppose to say:

deny from all

This should, under normal circumstances, deny direct access to the craft folder.


How can I import existing users with passwords stored in a different format than Craft's hash format? Se need to import a large user table to a Craft installation. Unfortunately, the passwords in the imported data are SHA1 encrypted (and salted).

What is the best way to enable the login of the users?

We thought that we add an extra column to the table which defined if the hash is standard or SHA1.

If a user logs in where the password is SHA1, then we check if it's the correct password and change it to the standard hash.

This would be the most comfortable way for the existing users.

Question: Is this a possible solution, especially is it possible to hook up into the login process to create the logic for the check.

Or would you recommend other solutions?

Short answer, it can't be done. Possibly with some extensive hacking, but I would highly caution against that.

Directly importing passwords isn't really possible, since the original passwords are unknown.
Adding a custom password column to the database is a bad idea, since Craft user/password management is pretty deeply embedded within the system.

Here's what I would recommend instead... Prompt your users to reset their passwords.

I know this idea doesn't seem ideal initially, but it is not unprecedented. People are used to changing their passwords occasionally, and will generally be very understanding about it. Many folks have dealt with systems that force them to change their password every 3 months, and everyone has forgotten a password at one time or another.

I recently had to do this for a website with several hundred users. We ported from EE to Craft, leaving the front-end visually identical. Here's the message we showed to users after the switch:

  Our login system has recently changed. Please note:

  If you haven't logged in since January 10th, you will be required to reset your password.


Output a default asset if one hasn't been specified I've looked at and tried a couple of solutions on here but struggling to apply them to my circumstance.

Below is my current code.  I would like a 'default' asset (image) to be used if one hasn't been specified by the admin.  This is so that the front end doesn't have gaps in the gallery.

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

      {% for block in entry.basicProfileInfo %}
      {% set varBarrPic = block.mx_peoplePhoto.first() %}

{{ block.mx_positionWithinBusiness }} {{ entry.title }}

      {% endfor %}

  {% endfor %}
{% endcache %}

I hope this is a simple solution.

Many thanks

Martin

You can test if your first() method returns an asset model.
And depending on that have different image URLs, the (transformed) asset's one or the URL of your placholder image.

{% set image = block.mx_peoplePhoto.first() %}
{% set imageUrl = image ? image.url('500x500') : url('images/_static/placeholder.jpg') %}

<img src="{{ imageUrl }}">

You could also consider to get that placeholder image from a global set.


relate pagination to entry on page I have managed to sort most Craft CMS questions out by reading the docs and feedback on StackExchange but am having issues with this one.

I have a page with a list of entries down the right side and the main entry content to the left.

The list is paginated.  When I go to say page 2 of the pagination and click on an entry, the page reloads with the page 1 pagination list.

How can I get the page to remember that the entry belongs to page 2?

{% paginate craft.entries.section('orchard').limit('5').id('not ' ~ entry.id)  as entriesOnPage %}

 {% for entry in entriesOnPage %}
   {% for asset in entry.mediaThumb %}

{{ entry.title }}

   {% endfor %}
 {% endfor %}

      {% if paginate.prevUrl %}

&laquo;

      {% endif %}
      {% for page, url in paginate.getPrevUrls(5) %}

{{ page }}

      {% endfor %}

{{ paginate.currentPage }}

      {% for page, url in paginate.getNextUrls(5) %}

{{ page }}

      {% endfor %}
      {% if paginate.nextUrl %}

&raquo;

      {% endif %}

{% endpaginate %}

Many thanks, Alex

You would need to pass the current pagination page number with your entry links and than make Craft
respond to URLs in a format like this: example.com/my-section/p2/my-entry-slug.

I guess this is more complicated than you'd think, as this is probably not possible to do with
the default paginate tag and its preset routes. And I also don't know of a way to combine the paginate
tag's page token with custom routes.

So I believe there's no other choice left than replacing paginate with a custom solution replicating its
functionality.

This is possible with dynamic routes and some logic in your templates. So you'd first have to set up a route
with a [page] and a [slug] token, which you can then access in your template.

my-section/p[page]/[slug] and
my-section/p[page]

I'll give some example code (untested and incomplete), to help you get started with the template.

All the pagination links build upon the route's page variable used in craft.entries's offset and limit parameters. With custom routes you also have to query for your entry entry model manually, I set it up to get the page's first entry
if there's no slug variable set from your route.

{# Set params #}
{% set params = {section: 'orchard'} %}
{% set entriesPerPage = 5 %}

{% if page is defined %}
    {% set offsetParam = (page - 1) * entriesPerPage %}
    {% set pageSegment = '/p' ~ page %}
{% else %}
    {% set offsetParam = 0 %}
    {% set pageSegment = '' %}
{% endif %}

{# Get the entry model #}
{% if slug is defined %}
    {% set entry = craft.entries.slug(slug).first() %}
{% else %}
    {% set entry = craft.entries(params).offset(offsetParam).first() %}
{% endif %}

{# Get pagination params #}
{% if page is defined %}
    {% set entriesOnNextPage = craft.entries(params).offset(offsetParam + 1) %}

    {% if entriesOnNextPage|length %}
        {% set nextPageSegment = '/p' ~ page + 1 %}
    {% endif %}

    {% if page == 1 %}
        {% set prevPageSegment = '' %}
    {% else %}
        {% set prevPageSegment = '/p' ~ page - 1 %}
    {% endif %}
{% else %}
    {% set entriesOnNextPage = craft.entries(params).offset(entriesPerPage) %}

    {% if entriesOnNextPage|length %}
        {% set nextPageSegment = '/p2' %}
    {% endif %}
{% endif %}

{{ entry.title }}

    {% set entriesOnPage = craft.entries(params).offset(offsetParam).limit(entriesPerPage) %}

    {% for entry in entriesOnPage %}
        {% set image = entry.mediaThumb.first() %}

    {% endfor %}

    {% if prevPageSegment is defined %}
        Previous Page
    {% endif %}

    {% if nextPageSegment is defined %}
        Next Page
    {% endif %}


what's the steps can i follow to develop module for send notification from CMS OP to windows phone application? i want to develop a windows phone application and receive notification from my CMS opencart
So to send notification from my CMS, i must develop a module !

what's the steps can i follow to develop module for send notification from CMS OP to windows phone application?

An incredibly broad question deserves an incredibly broad answer... You'll need to build a plugin:

  http://buildwithcraft.com/docs/plugins/introduction

(Apologies for the snarkiness)


Make sort dropdown keep property I've got a working sort dropdown on my front end, but I'm after the dropdown keeping the chosen sort method option instead of resetting to the default top of the dropdown option.

e.g. User clicks sort by Name A - Z > Sorted by name > Dropdown option stays as 'Name A-Z' instead of 'default'.

    <select class="sort-web w-select" data-name="Sort" id="sortQuery" name="Sort">
        <option value="postDate asc">New - Old</option>
        <option value="title desc">Name Z - A</option>
        <option value="title asc">Name A - Z</option>
    </select>

Craft Code

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

{% for category in craft.categories.group('university').order(order) %}
  {{ category.title }}
{% endfor %}

JS

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

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

     // Get the value from the select
     var filter = $(this).val();
     document.location.href = '{{ craft.request.getUrl() }}?order=' + filter;

   });

  });
{% endset %}
{% includeJs orderJs %}

Any help would be greatly appreciated!

In short, you need to set the selected attribute on the option element based on the sort order.

So, if the sort order is title asc, then that option would have the selected (selected="selected") attribute set on it.

I took the liberty to refactor your code to render sort options dynamically and make the selected sort order sticky by comparing the current option being iterated over, against the selected sort option.

{% set sortOptions = [
    {
        label: 'New - Old',
        value: 'postDate asc'
    },
    {
        label: 'Name Z - A',
        value: 'title desc'
    },
    {
        label: 'Name A - Z',
        value: 'title asc'
    },
] %}

{% set selectedSortOption = craft.request.getParam('order', 'title asc') %}

{% for category in craft.categories.group('university').order(selectedSortOption) %}
    {{ category.title }}
{% endfor %}

<select class="sort-web w-select" data-name="Sort" id="sortQuery" name="Sort">
    {% for sortOption in sortOptions %}
        <option value="{{ sortOption.value }}" {{ sortOption.value == selectedSortOption ? 'selected' }}>
            {{ sortOption.label }}
        </option>
    {% endfor %}
</select>

Feel free to follow up if you have any questions.


Output entry title in subject line of notification when sprout form is submitted I am new to this so, excuse the lack of proper terminology. But I am using the Sprout Forms plugin (v1.1.0) on a site we designed for a real estate client. What I am hoping is that a visitor could fill out a form, and then the notification email would include the page title {{entry.title}} of the page which the form was filled out on. Otherwise would I need to create a unique form for every page in a craft "channel?" The site url is http://sivelluxury.com...

I've currently got this in the subject line of the notification pane for that contact form - {fullName} Submitted a contact form on {{entry}} was filled on {{ siteName }} {dateCreated|date('Y-m-d')}

Anyone who can help me?

This is now possible with Sprout Forms 2.0 and Sprout Fields 1.0 Hidden or Invisible Field.

You'll need to make your entry available to the Hidden of Invisible field using the addFieldVariables tag, and then in your field settings you can reference the Entry ID using single curly braces: {entry.id}

{# Make the Entry available to your Hidden or Invisible field settings #}
{% do craft.sproutForms.addFieldVariables({ entry: entry }) %}

{# Output your form as normal #}
{{ craft.sproutForms.displayForm('contact') }}

See Setting a dynamic value (outside the global scope).

Legacy Answer (pre Sprout Forms 2.0)

When a form is submitted, the form notification has access to the variables in the SproutForms_EntryModel which include all the custom fields submitted with the form and anything in the global scope such as {{ currentUser.email }}.

To make the Subject Line of the page that the form was submitted from available to your notification, you will need to make it a field on your form.

This may be a little tricky to do with dynamic forms right now, but we are working on a way to make this easier in the future using a Hidden Field field type.

A couple approaches to consider right now:

Write a Hidden Field custom field type that behaves like you need it to
Build your form with custom HTML and populate a hidden field on your form with the {{ entry.title }} value.
Create a "Page Title" Plain Text field on your form, style it to display:none so the user never sees the field there, and populate the field with the entry title using javascript.


How would I change "disabledElementIds" when using createElementSelectorModal()? I'm using the createElementsSelectorModal to access certain element types as described by Brandon here

With this implementation, how would I clear out "disabledElementIds"? So that if an Entry is added and then removed I can tell the Modal it should be selectable again.

Thanks!

Elements can be manually enabled/disabled from the modal after it has been initialized using the following methods:

myModal.elementIndex.enableElementsById(elementIds);

and

myModal.elementIndex.disableElementsById(elementIds);

Both functions accept a number (single element ID) or an array of numbers (multiple element IDs).


Not all assets copied over when copying an entry from admin panel I have a site with multiple locales.  I have some entries that will have some basic fields such as title, description, etc and also an asset field.  The asset field is translatable so I could have an English PDF and a French PDF for the entry.  We often copy over entries and I have noticed when we do it will copy over the English asset but not the French asset.  Often times some admins are not aware they have to go back and re-add the French asset which is causing issues.

I am wondering if this is by design, a bug or ideally is there any setting or workaround I could do to fix the issue.

I am doing this in the admin panel when editing an entry and clicking on the arrow on save and selecting save as new entry.

Thanks

Im hesitant to say that this is by design because iam not entirely sure what you mean. Instead i'll explain something i think is comparible that happend to us. We have an entry channel with entries which act as the companies of users on the website. When we saved a company profile in Dutch, fields such as the description or company info would not pull across. We fixed this by listening to the onSaveEntry event and simply pulling the fields across manually. This isnt a very pretty or portable way to do it - but this was an incredibly case and website specific feature - we only wanted entries in this website and even just in this section to have this 'copying' feature. From memory the script looked something like the below:

One word of advise i would issue if of advice i would give is if you are working with other content editors is to listen to the cp.entries.edit.right-pane hook and build a small interface that allows them to select the locale and copy over the current locale to the new locale. The script below has one downside which is that it essentially sterilizes the localization function for craft for the affected entries - which in this projects case was crucial - but in yours probably isnt.

Let me know if anything is unclear. One word of notice - if you are working with a relations field which is what a pdf should be. Relations should be copied over IF you are using something like 'Save as a new entry'. If this isnt happening you've probably found a bug.

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

        // Does the entry section equal our companies section channel?
        if (craft()->isLocalized() && $entry->sectionId == 2) {

                // What locales are there?
                foreach (craft()->i18n->getSiteLocales() as $locale)
                {
                    // Is this a foreign locale
                    if ($locale != $entry->locale)
                    {
                        // Get an entry that belongs to this with a sep locale, setup a model and save it.
                        $otherLocaleEntry = craft()->elements->getElementById($entry->id, ElementType::Entry, $locale->__toString());
                        if ($otherLocaleEntry)
                        {
                            $otherLocaleEntry->getContent()->myFieldsStuff = $entry->getContent()->myFieldsStuff;

                            craft()->entries->saveEntry($otherLocaleEntry);
                        }
                    }
                }
            }
        }
    });


Commerce Stripe Card Declined shows white screen with no error I've got an issue when cards are declined and only a white screen is shown to the user without any feedback. The url has not changed at all either.

This is happening on the live Stripe account so I set up a dev site and used the test account and saw the same when using the
4000000000000002 card number, devMode is enabled but no errors were returned.

Here are the relevant bits of my JS code which handle the creating of the card token and showing any errors encountered:

function stripeResponseHandler(status, response) {
    // Grab the form:
    var $form = $('#payment-information');
    if (response.error) { // Problem!
        if ($('#stripeToken').length) {
            $('#stripeToken').remove();
        }
        // Show the errors on the form
        $('#payment-information').find('.payment-errors').show().find("p").text(response.error.message);
        return false;
    } else { // Token was created!
        // Get the token ID:
        var token = response.id;
        // Insert the token into the form so it gets submitted to the server:
        if ($('#stripeToken').length) {
            $('#stripeToken').val(token);
        } else {
            $('#payment-information').append($('<input type="hidden" id="stripeToken" />').val(token));
        }
        $('#payment-information').find('.payment-errors').hide();
        $("#payment-information").submit();
        return true;
    }
}

Stripe.card.createToken({
    name: $('input[name="firstName"]').val()+" "+$('input[name="lastName"]').val(),
    number: $('#payment-card-number').val(),
    cvc: $('#payment-cvt-code').val(),
    exp_month: $('select[name="month"]').val(),
    exp_year: $('select[name="year"]').val(),
    address_zip: $('#shippingAddress-zipCode').val()
}, stripeResponseHandler);

Payments are going through fine on the live site and errors such as invalid card numbers are being shown correctly. However, 4000000000000002 is a valid card number and therefore the token is being created successfully without any errors. This is what is happening on the live site when payments are being declined for customers.

When this is then submitted through the commerce/cartPayment/pay form, no errors are shown, just a white page. Has anyone else encountered this and found a way around it? Thanks.

Couldn't get past the white page issue so I made a simple plugin which does the following:

craft()->on('commerce_transactions.onSaveTransaction', function($event) {
    $transaction = $event->params["transaction"];
    if ($transaction->status == "failed") {
        $message = $transaction->response["error"]["message"];
        craft()->userSession->setNotice($message);
        craft()->request->redirect('/order');
    }
});

Thank you for your help Luke Holder. Strange that I couldn't get rid of the white page but at least we found a solution in the end to stop the issue on the live site whilst customers are making payments.


Can traits be loaded in plugins? I have a number of different models that have custom validation methods, some of which are shared across models.

Due to the combinations I can't use class inheritance to share those methods, so I wondered if traits are supported and if so, what the convention would be?

Traits are just a PHP thing not related to Craft at all so yes, you could use them.  But you'd be limiting your plugin to PHP 5.4+ only since that's when they were introduced.

Craft 2.x supports back to PHP 5.3.

You might also want to look at Yii's Behaviors, which have similar functionality to traits and works with PHP 5.3.

Craft 2.x uses a few behaviors of its own.


Sideloading an image from a function in a plugin I need to be able to side load an image and attach to an entry.

My image is coming from an external url... such as http://someplace.com/image.jpg - i can store this in a temporary file so its locally accessible.  But then how do I upload this image (without using $_POST or $_FILES) and attach to an entry.

The method i'm trying at the moment i'm using something like:
uploadNewAsset(UploadedFile $uploadedFile, $folderId)

But UploadedFile seems to only want to accept POST variables, unless i'm missing something

Any help would be great

Thanks

You can see an entire example how to fetch a file via curl, save it into an asset and relate it to an entry here

// get the entries service
$entries = Craft::$app->getElements();

// get the entry
$entry = \craft\elements\Entry::find()->one();

// somehow grab the path of your image
$client = Craft::createGuzzleClient();
$response = $client->get('https://www.google.com/logos/2018/halloween18/rc5/cta.png');

$image = $response->getBody()->getContents();
$path = Craft::$app->getPath()->getTempPath() . DIRECTORY_SEPARATOR  . 'someFile.png';
FileHelper::writeToFile($path, $image);

// the folder for the image
$folder = Craft::$app->getAssets()->getFolderById(1);

// create a new asset
$asset = new \craft\elements\Asset();
$asset->tempFilePath = $path;
$asset->filename = 'someFileName.jpg';
$asset->title = 'someTitle';
$asset->newFolderId = $folder->id;
$asset->volumeId = $folder->volumeId;
$asset->avoidFilenameConflicts = true;
$asset->setScenario(\craft\elements\Asset::SCENARIO_CREATE);
if($entries->saveElement($asset) === true){
    // file was saved
    $entry->setFieldValue('assetFieldHandle', [$asset->id]);
    $entries->saveElement($entry);
}


relatedTo working for one category group but not another I'm trying to show a list of entries related to the same category on a page that contains a single entry. I have two category separate category fields in the entry, both with one category each selected in them. The two category groups are named eventType and venue. The code below successfully shows a list of entry titles for one category group but not the other, and I can't seem to find out what's going wrong.

The code below works for the eventType category group (it shows all the entries related to eventType). But when I swap out eventType for venue, it returns my else statement.

I'm new to Craft (it's great!), so maybe I'm going about this all wrong, or missing something obvious.

{% for thisCategory in entry.eventType %}

Other Events in {{ thisCategory.title }}

    {% set category = craft.categories.slug(thisCategory.title) %}
    {% set entries = craft.entries.section('events').relatedTo(category).find() %}

    {# If there are any entries, loop through them #}
    {% if entries | length %}
        {# For each entry we find, do this #}
        {% for entry in entries %}

{{ entry.title }}

        {% endfor %}
    {% else %}

Found no entries

    {% endif %}
{% endfor %}

Your approach seems interesting but you should never do such "relations". They can be broken all over the way. Let me explain that.

Title vs Handle

Most objects in Craft have the attributes title and handle. The title is the name that can be rendered in the frontend. This should be your attribute to show users what the object is about. The handle is your "developing" attribute. This is a unique field, with several validation rules to make this field selectable via getEntryByHandle() thus you can link entries via handle, get them via handle and change the display name (title) however you like and can still select those via handle.

Other Events in {{ thisCategory.title }}

Is totally correct, you show the title to the frontend

{% set category = craft.categories.slug(thisCategory.title) %}

Is absolutely wrong. The validation rules for title and the validation rules for the slug attribute are totally different and you should never match those fields. When you have a title like Foo Bar you'll never be able to match them since your slug would be foo-bar.

The correct way would be this

{% set category = entry.yourCategoryFieldHandle.first() %}
{% set entries = craft.entries.section('events').relatedTo(category).find() %}

If you really really want to relate objects not via the relation Field but via strings you should do it with the handle but never with titles or slugs


How would I write this differently to make it compatible with MYSQL 5.7 There is an issue with using unique => true in defining an attribute as a primary key when using MYSQL 5.7.*.

protected function defineAttributes()
{
    return array(
        'eid' => array(AttributeType::Number, 'unique' => true, 'column' => ColumnType::PK)
    );
}

According to my setting this error should not occur. Here is the error.

CDbCommand failed to execute the SQL statement: SQLSTATE[42000]: Syntax error or access violation: 1171 All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead

Here is the SQL executed.

system.db.CDbCommand.execute(CREATE TABLE `craft_venti_events` (
    `eid` int(11) NOT NULL AUTO_INCREMENT NULL,
    `eventid` INT(10) NULL,
    `startDate` datetime NULL,
    `endDate` datetime NULL,
    `allDay` INT(10) NULL,
    `repeat` INT(10) NULL,
    `rRule` VARCHAR(255) NULL,
    `summary` VARCHAR(255) NULL,
    `isrepeat` INT(10) NULL,
    `locale` VARCHAR(255) NULL,
    `dateCreated` datetime NOT NULL,
    `dateUpdated` datetime NOT NULL,
    `uid` CHAR(36) NOT NULL DEFAULT 0,
    PRIMARY KEY (eid)
) ENGINE=InnoDb DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci)

Turns out this is a bug as of Craft 2.6.2931 with the ColumnType::PK enum
in a record's attribute type definition.

Pretty sure it'd be a bug in < MySQL 5.7 because it's invalid SQL syntax as well unless they're just more forgiving of it there.

This is a non-issue in the upcoming Craft 3 release (the concept of attributes no longer exists and plugins explicitly define their table schema create statements), but the workaround for Craft 2 until the bug is fixed is to not use a record here and manually create the table schema that you need by adding an onBeforeInstall method to your plugin.


Saving to Table Field Type via Plugin I keep getting a server error when attempting to save data to a table field. This is the code I am using test data insertion. (251 is a valid enteryId)

    $entry = craft()->entries->getEntryById(251, $localeId = null);
    $arr = array('col1' => 'some sku', 'col2' => 'This is a big fat description', 'col3' => 495.00, 'col4' => 0);
    $arr = json_encode($arr);
    $entry->getContent()->gistDistribution = $arr;
    $success = craft()->entries->saveEntry($entry);

This is my error:

Internal Server Error
Illegal string offset 'sku'

Note: sku is a column name in my table field.

NOT TESTED

I think you can just add an array to gistDistribution, it will get
json_encoded before saving.
I think you'd have to set the variable like this:

$arr[0] = array(...);

That way, you provide a multidimensional array, which is what a table needs.


Need to make a wish list / favourites system Has anyone made a plugin which allows for a visitor/user to remember an entry and then see a list of them?

I need to make a "short list" page for our new site.

I was sure there was a plugin that did this, but I can't for the life of me find it anywhere now!

I know this is a bit late for your specific question, but Shortlist for Craft is designed for exactly this.

(I'm the developer).

It's also available for EE


Disabled product variant still shows in {% for %} loop Disabling a product variant doesn't remove it from a {% for purchasable in product.variants %} loop I have set up. It still renders an image associated with it, as well as a color swatch. Essentially not disabling it at all.

{% for purchasable in product.variants if purchasable.status('live') %} isn't working either, which I assume is only applicable to the product model.

Any ideas?

This should filter the variants by their enabled status:

{% set product = craft.commerce.products.id(productId).first() %}

{% for variant in product.variants if variant.enabled %}
    {{ variant.id }}
{% endfor %}


Eager-Loading child elements in a multi-level structure section I have a structure that looks like this:

Experiment ( Level 1)

Cages (Level 2)
Animals (Level 3)
Measurement (Level 4)

I am outputting this information into some inline JSON like so:

{% set mice = craft.entries({
    'section' : 'experiments',
    'level' : 3,
    'descendantOf' : entry.id,
}) %}

<script>
  var data = [
    {% for mouse in mice %}
    {
      "Cage": "{{ mouse.parent.title }}",
      "Mouse": "{{ mouse.title }}",
      "measurements": [
        {% for data in mouse.children.order('postDate') %}
        {
          "Date": "{{ data.postDate| date("d-M") }}",
          "Weight(g)": "{{ data.weight }}",
          "Length": "{{ data.length }}",
          "Depth": "{{ data.depth }}",
          "Tumor Volume": {{ data.tumourVolume }}
        }{% if not loop.last %}, {% endif %}
        {% endfor %}
      ]
    }{% if not loop.last %}, {% endif %}
    {% endfor %}
  ];
</script>

This is ok until entries start to increase, the TTFB begins to add up significantly - I am wondering if there is a way to eager load this sort of structure? The entries are very dynamic so caching isn't an option.

Thanks!

To use eager-loading for the child elements add 'children' to the with parameter.

{% set mice = craft.entries({
    section: 'experiments',
    level: 3,
    descendantOf: entry.id,
    with: ['children', {order: 'postDate asc'}],
}) %}


Hacksaw plugin breaking rich text field When I use the hacksaw to truncate the formatting goes away.  If I remove hacksaw it comes back.  So, my question has changed, is there a way for me to truncate the text while keeping the formatting?

The return on the line below is from a rich text field and it will not show formatting unless I remove hacksaw.

 {{ workItem.summary | hacksaw(words='75', append='...') }}

Hacksaw has an allow parameter where you specify which HTML tags you want it to pass through.

You might want to try something like:

{{ workItem.summary | hacksaw(words='75', append='...', allow='

') }}

That allows p, br, strong, and em tags to pass through untouched. If you need to allow others, just add 'em to the list.


Different Single as homepage for other languages How can I give another localization its own "Single" as homepage. My main language has its own very unique homepage but for the other languages I need all the fields and HTML/CSS of my about us page. I want to do this without adding all the fields to some other tab in my homepage.

Is there any possible way to make this happen. I tried already to set the homepage for the main language open. Created a new Single for the other language but I dont have the option to set it as homepage for the current language.

You don't need to use the "This is for the homepage" checkbox at all. All it does is to (1) set up
a route to the entry template specified in the section settings and (2) make the entry model available to this template
from an entry variable.

You can just deselect this option and configure the above manually. The simplest way to set up a route for the homepage is
to create a template index.html in craft/templates/ and Craft picks it up automatically for hompage requests (→ see pt. 6 in the routing docs).

You can now query for the entry model (your "single") depending on the requested locale to solve (2) and then include a template partial
into the index.html to solve (1).

{% if craft.locale == 'fr' %}
    {% set entry = craft.entries.section('home_fr').first() %}
    {% include '_pages/home_fr' %}
{% elseif craft.locale == 'de' %}
    {% set entry = craft.entries.section('home_de').first() %}
    {% include '_pages/home_de' %}
{% else %}
    {% set entry = craft.entries.section('home').first() %}
    {% include '_pages/home' %}
{% endif %}


Select query question I am trying to do the following with craft.entries but I think it may not be possible without a plugin.

I have 9 categories with related entries on all of them. I would like to get the latest articles (postDate) for each one the categories and then group by category and only show only the seven latest articles, one for each category.

The following works but it fetches 100 articles each time (I can reduce it but still its not ideal)

{% set latestArticles = craft.entries.section('articles').relatedTo({element: selectedCategories, field: 'journalismMainCategory'}).order('postDate desc').find() %}
{% set groupedArticles = latestArticles|group('journalismMainCategory.first.id')|slice(0,7) %}

I've also tried the following but I cannot get it to sort by date or group the category properly. It retrieves the latest article for each category, but in the order of the category (and not by post date)

{% set selectedCategories = [98, 100, 2412, 2408, 2410, 2414, 2416, 55332, 55333] %}

{% for category in selectedCategories %}
       {% set stilesArticles = stilesArticles|merge([craft.entries.section('articles').relatedTo({element: selectedCategories[loop.index0], field: 'journalismMainCategory'}).limit(1).first]) %}
{% endfor %}

Any ideas on how something like this can be done without a plugin?

Cheers!

Why don't you use the prepared ElementCriteriaModel in the category and change the query?

{% for category in craft.categories.group('whatever') %}
    {% set articles = category.journalismMainCategory.limit(7).order('postDate').find() %}
{% endfor %}

Your category.journalismMainCategory contains an ElementCriteriaModel that will fetch all related entries you can include a limit, change the sort order and execute it, so you'll receive 7 articles with the correct order for each of your categories

Edit: link to the docs


.env parsing error on Windows server Has anyone had issues with Craft parsing a .env on Windows Server?   Dotenv is throwing an exception (FileException - invalid name) when parsing the first line of my .env, which is just a comment. I can remove that line and then i complains about the next line.
My .env simple starts with:
# The environment Craft is currently running in (dev, staging, production, etc.)
ENVIRONMENT=dev

basically, Dotenv/Parser/isValidName's Regex call is failing.
Full Stack...
Fatal error: Uncaught Dotenv\Exception\InvalidFileException: Failed to parse dotenv file due to an invalid name. Failed at [ENVIRONMENT]. in C:\WebRoot\WebApplications\advantage-rebate-portal-v4.0\vendor\vlucas\phpdotenv\src\Parser.php:74

Stack trace:
#0 C:\WebRoot\WebApplications\advantage-rebate-portal-v4.0\vendor\vlucas\phpdotenv\src\Parser.php(30): Dotenv\Parser::parseName()

#1 C:\WebRoot\WebApplications\advantage-rebate-portal-v4.0\vendor\vlucas\phpdotenv\src\Loader.php(169): Dotenv\Parser::parse()

#2 C:\WebRoot\WebApplications\advantage-rebate-portal-v4.0\vendor\vlucas\phpdotenv\src\Loader.php(107): Dotenv\Loader->processEntries()

#3 C:\WebRoot\WebApplications\advantage-rebate-portal-v4.0\vendor\vlucas\phpdotenv\src\Loader.php(91): Dotenv\Loader->loadDirect()

#4 C:\WebRoot\WebApplications\advantage-rebate-portal-v4.0\vendor\vlucas\phpdotenv\src\Dotenv.php(123): Dotenv\Loader->load()

#5 C:\WebRoot\WebApplications\advantage-rebate-portal-v4.0\vendor\vlucas\phpdotenv\src\Dotenv.php(80): Dotenv\Dotenv->loadData()

#6 in C:\WebRoot\WebApplications\advantage-rebate-portal-v4.0\vendor\vlucas\phpdotenv\src\Parser.php on line 74

Turns out it WAS a file encoding issue. It was UTF BOM (?), and had a weird hidden character right at the beginning of the file. I was able to open the file up in Notepad++ (Thanks Brad) and was able to convert the file to "normal" UTF8.


Simple webshop solution (Craft Commerce)? I am looking for a simple shopping solution for one of my customers. Since their website is already running with CraftCMS, I am looking if there is any integrated solution available.

However, so far I have found only 3 plugins compatible with Craft3:

Stripe Payments
PayPal Buy Now Button
Craft Commerce

Am I missing one?

Does anyone have experience with one or more of these shop systems?

Right now, Craft Commerce Lite looks the best to me, but I am not sure whether I am overlooking something.

You could use https://snipcart.com/, with the product data populated via Craft fields, for an easy/low-cost solution.

No plugin required for this - although https://superbig.co/plugins/snipcart is in the works for an even tighter integration.

For example see https://www.bernatkleinfoundation.org, here's a screenshot of the product entry used to populate products in Snipcart:


Entries where field = current month? I'm trying to pull entries from an events channel where a date field falls in the current month.  Through google and other SE posts I've gotten to the following code:

{% set currMonth = now|date('m') %}
{% set currMonthFirst = currMonth ~ '/1/' ~ now|date('Y') %}
{% set nextMonthFirst = currMonthFirst|date_modify('+1 month') %}

{{ currMonthFirst|date('m/d/Y') }} - {{ nextMonthFirst|date('m/d/Y') }}

{% set events = craft.entries.section('events').event_startDateTime('>= ' ~ currMonthFirst|date('m/d/Y') ~ ', <' ~ nextMonthFirst|date('m/d/Y')) %}

{% for event in events %}

{{event.title}}

{% endfor %}

currMonthFirst and nextMonthFirst both output the dates I'd expect, but when I use the set & for loop I get the following error - Fatal error: Call to a member function getTimestamp() on a non-object.  Any idea what I'm doing wrong here or how to make what I'm trying to do work?

This should get it sorted.  There were 2 issues with yours.  First is you were using the wrong 'and' syntax in the craft.entries call and second you need to use the Y-m-d pattern so MySQL understands to convert it a proper DateTime field instead of the m/d/Y format you had.

{% set currMonth = now|date('m') %}
{% set currMonthFirst = now|date('Y') ~ '-' ~ currMonth ~ '-1'  %}
{% set nextMonthFirst = currMonthFirst|date_modify('+1 month') %}

{{ currMonthFirst|date('Y-m-d') }} - {{ nextMonthFirst|date('Y-m-d') }}

{% set events = craft.entries.section('events').event_startDateTime('and', '>= ' ~ currMonthFirst|date('Y-m-d'), '< ' ~ nextMonthFirst|date('Y-m-d')) %}

{% for event in events %}

{{event.title}}

{% endfor %}

Completely untested, but try using:

{% set events = craft.entries.section('events').event_startDateTime('and', '>= ' ~ currMonthFirst|date('m/d/Y'), '< ' ~ nextMonthFirst|date('m/d/Y')) %}


Displaying entires by year from a custom date field I have a date field (date) in my entry and I wish to get all entries of a specified year.  Can’t figure it out at all.  Here’s what I have now, to sort them by that field:

craft.entries.section('evenements').order('date desc')

My "year" is passed to the page through routing and is named "year".  I can get that.

Thanks

Looks like I finally found an answer to it

year being my param

date being my custom date field

{% set dateParam = 'and, >= ' ~ year ~ '-01-01, < ' ~ (year + 1) ~ '-01-01' %}

    {% for entry in craft.entries.section('evenements').order('date desc').date(dateParam) %}

{{ entry.title }}

    {% endfor %}


Member ControlPanel Logs? Are there some logs which tell, what the member does in the backend?

Something like: "User: «John Doe» Edited this entry at this and that date".

Just a bit more information than what is written on the member account:

Not currently... we've discussed adding a sort of audit or activity trail to Craft itself, but haven't flushed out any details or timeline.

In the meantime, you could probably get 95% there with a custom plugin that listens to the various Craft events you're interested in.


Can't install Transcoder plugin Not sure whether I should be posting this here or as a Github issue, but when trying to install NY Studio's Transcoder plugin, I get:

Composer output: Package "craftcms/vue-asset" listed for update is not installed. Ignoring.
Package "yiisoft/yii2-shell" listed for update is not installed. Ignoring.
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.
Problem 1
The requested package nystudio107/craft-seomatic (locked at 3.3.17, required as ^3.3.18) is satisfiable by nystudio107/craft-seomatic[3.3.17] but these conflict with your requirements or minimum-stability.
Running update with --no-dev does not mean require-dev is ignored, it
just means the packages will not be installed. If dev requirements are
blocking the update you have to resolve those problems.

composer.json looks like this:
{
  "require": {
    "barrelstrength/sprout-fields": "^3.8.3",
    "craftcms/cms": "^3.4.24",
    "craftcms/redactor": "^2.6.1",
    "dukt/analytics": "^4.0",
    "nystudio107/craft-seomatic": "3.3.18",
    "nystudio107/craft-typogrify": "^1.1",
    "ostark/craft-async-queue": "^1.3.3",
    "putyourlightson/craft-blitz": "^3.6.5",
    "topshelfcraft/wordsmith": "^3.2.0",
    "verbb/cp-nav": "^3.0.13.1",
    "verbb/field-manager": "^2.1.8",
    "vlucas/phpdotenv": "^2.4.0"
  },
  "autoload": {
    "psr-4": {
      "modules\\": "modules/",
      "modules\\exifReturn\\": "modules/"
    }
  },
  "config": {
    "sort-packages": true,
    "optimize-autoloader": true,
    "platform": {
      "php": "7.0"
    }
  },
  "scripts": {
    "post-root-package-install": [
      "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
    ]
  },
  "repositories": [
    { "type": "composer", "url": "https://packagist.phpcomposer.com"}
  ]
}

Has anyone else had this problem and how did you resolve it?

Try changing it to this:
    "nystudio107/craft-seomatic": "^3.3.0",


First steps with Craft Nitro: hostname not working after successful install I installed Docker and Nitro and successfully used nitro create <folder-name>, and ended up with the 'Welcome to Craft CMS!' message.
I cded into the new folder and invoked ./craft setup, which along the way has reported 'success!' at testing database credentials.
After saying yes to installing on the command line and creating an admin user account, I've received:
*** installed Craft successfully (time: 12.240s)

Generating project config files from the loaded project config ... done

I can see my new local dev instance running in Docker.app, but when I go to the site in a browser I get 503 – Service Unavailable.
If I go to {hostname}/admin I get the browser prompt to Install Craft. If I try and fill that out I get PDO exception: SQLSTATE[HY000] [2002] Connection refused.
The potential ease of use of Nitro looks really promising so it's frustrating to be so close!
What could I be missing?

Update 1
I have the following in my .env:
DB_DRIVER=mysql
DB_SERVER=127.0.0.1
DB_PORT=3306
DB_DATABASE=<dbname>
DB_USER=nitro
DB_PASSWORD=nitro
DB_SCHEMA=
DB_TABLE_PREFIX=

where <dbname> is the DB name I was asked to define (during nitro create I think) and which it said it could connect to.
Under 'Databases' nitro context reports:
Databases:
  engine:        mysql 5.6      hostname: mysql-5.6-3306.database.nitro
  username:      nitro  password: nitro
  port:  3306

Update 2
To start from scratch, I junked my nitro instance in Docker and uninstalled nitro, and then reinstalled it, and went through nitro create again, and…
ended up in basically the same place.
I've tried my custom database name as the value of DB_DATABASE and the default nitro database name, and it makes no difference.

After cheating via discussion in the comments, I’m certain that your DB_SERVER is incorrectly set to 127.0.0.1 when it should in fact be mysql-5.6-3306.database.nitro.
In a perfect world this would have been set for you when Nitro edited .env, but in a pandemic-ravaged dystopia your next best option is to use whatever nitro context indicates.


How can I disable/decrease the number of calls to getAuthTimeout? The host of a client is claiming the call to getAuthTimeout is triggering their firewall, and in turn blocks my client from accessing their site for a longer duration.

Is there a way to disable or change the interval?

Unfortunately, the AJAX call to getAuthTimeout is hard coded to fire every 60 seconds. In other words, if you're looking for a config value, there isn't one – might be worth a feature request?

For a quickfix/hack, you can create a custom plugin and add the following to its init method:

craft()->templates->includeJs('(function () {
    Craft.AuthManager.checkInterval = 600; // Ten minutes
}());', true);

You can change the 600 to any number of seconds, of course.

If you want to kill the timeout check completely, you can do this instead of the above:

craft()->templates->includeJs('(function () {
    Craft.AuthManager.prototype.setCheckAuthTimeoutTimer = function () {};
}());', true);

Of course, both of these snippets are total hacks. Use with caution!

One important thing to note is that I don't think its possible to stop the first AJAX call to getAuthTimeout (which will fire after 60 seconds). The reason is that by the time the JavaScript hack inside the includeJs handler has fired, the Craft.AuthManager class has already been initialized and created the first timeout object. There's no reference to this timeout stored anywhere on the Craft object (that I've been able to find, at least), which makes it impossible to clear it, unfortunately.


Next in structure if lightswitch field off? I'm trying to get the next field in an entry if a passwordRequired Lightswitch Field is switched off.

How would I go about that?

If you are really trying to get the next field in order on an entry type:

Field order can't be set on an entry type's field layout. Craft seems to set their order when you create them in Settings->Fields. Whatever you are trying to setup/accomplish this way I would recommend against.

If you are trying to retrieve entries that the lightswitch field is off:

{% for entry in craft.entries.section('sectionHandle').all().lightSwitchField('not 1') %}
{{ entry.field }}
...

If you are trying to get the sibling of an entry if the current entry's lightswitch field is off:

{% if not entry.lightswitchField %}
    {% set sibling = craft.entries().nextSiblingOf(entry).one() %}
{% endif %}

I tried to give you several examples/solutions as your question isn't explicit.


Preserving  tags inside a  tag in a Redactor rich text field If I have multiple paragraphs of text in a rich text field, and I select them all and select "Quote" from the formatting menu, the
 tags are stripped out and replaced with double
 tags, like so:

This is some text.

Here's some more text.

Is there any way to preserve the
 tags, like so?

This is some text.

Here's some more text.

I've been through the Redactor documentation and config settings and haven't found anything that seems relevant.

Would you consider an alternative Matrix based approach where one rich text field was used for article-copy and another separate rich text field, used for the blockquote?

So: Matrix field: "Article blocks"

Block 1: "Article"
Block 2: "Quote"

e.g. (screen shot from a current project...)

That way you could leverage Matrix functionality and allow more layout control as well - such as alignment etc - to the blockqoutes, and maintain your paragraphs as well.


Exclude categories that are not associated to any entry I have a set of categories that I would like to display on a sidebar as a way to filter the list of entries displayed. However, some of those categories haven't been associated with any entries yet so clicking on that category with return 0 results.
What is the most efficient way to exclude those categories?

You could get the entries ids, then get the categories related to those entries.
Like so:

{%- set ids= craft.entries.section('sectionHandle').ids() -%}

{%- for cat in craft.categories.relatedTo({ sourceElement: ids }).group('categoryHandle') -%}
    {{- cat.title -}}
{%- endfor -%}

That will only print categories with an entry associated with.


Category name in page title All I'm trying to do is put the category title on a category listing page into the title tag.
So I've got the variable set up, but if I add the category title tag:

{% set title = "{{ category.title }}" %}

The end result is this

<title>{{ category.title}}</title>

So do I need to escape the quotes?

You don't have to fill in the quote's or the curly brackets.

You could just put it down like this:

{% set title = category.title %}

You already "called" twig so you dont need to do that again.


How can I insert images into a Redactor rich text field in a front-end form? I want to allow registered users to insert (i.e. upload) images into a Redactor rich text field in a front-end form.

I dowloaded the Image Manager plugin from Imperavi (https://imperavi.com/redactor/plugins/imagemanager/) and set up my Redactor config as follows:

{% includeJsResource "lib/redactor/redactor.js" %}
{% includeJsResource "lib/redactor/plugins/source.js" %}
{% includeJsResource "lib/redactor/plugins/fullscreen.js" %}
{% includeJsResource "lib/redactor/plugins/imagemanager.js" %}
{% includeCssResource "lib/redactor/redactor.css" %}

{% set redactorJS %}
    $('#{{ elId }}').redactor({
        buttons: ['format', 'bold', 'italic', 'deleted', 'lists', 'link', 'html', 'image'],
        formatting: ['p', 'blockquote', 'h2', 'h3'],
        plugins: ['source','fullscreen', 'imagemanager'],
        minHeight: 300,
        imageUpload: '/upload.php',
    });
{% endset %}
{% includeJs redactorJS %}

I can see the image button in the toolbar and the browse files modal when I click the image button. However, it doesn’t upload anything because imageUpload: '/upload.php', is obviously incorrect. What, if anything, can I replace upload.php with? If this isn’t possible, what else could I do to achieve this functionality? Thanks!

UPDATE:

I have the following code in craft/plugins/imagesuploaderscript/controllers/ImagesUploaderScriptController.php from CloudApp share link in comment below:

namespace Craft;

class ImagesUploaderScriptController extends BaseController
{

protected $valid_extensions = array('jpg', 'jpeg', 'png');
protected $assetSourceId = 1;
protected $assetFolderId = 1;

public function actionUpload()
{
    $this->requireAjaxRequest();

    $errors = array();
    $success = array();

    if (!$_FILES['file']['error'])
    {
        $filename = $_FILES['file']['name'];
        $file = $_FILES['file']['tmp_name'];
        $extension = pathinfo($filename, PATHINFO_EXTENSION);

        if (!in_array($extension, $this->valid_extensions))
        {
            $errors[] = "$filename has an invalid extension.";
        } else {
            $uploadDir = craft()->assetSources->getSourceById($this->assetSourceId)->settings['path'];

            if (move_uploaded_file($file, $uploadDir . $filename))
            {
                IOHelper::deleteFile($file);

                $file = $uploadDir . $filename;

                $fileModel = new AssetFileModel();
                $fileModel->sourceId = $this->assetSourceId;
                $fileModel->folderId = $this->assetFolderId;
                $fileModel->filename = IOHelper::getFileName($filename);
                $fileModel->kind = IOHelper::getFileKind(IOHelper::getExtension($filename));
                $fileModel->size = filesize($file);
                $fileModel->dateModified = IOHelper::getLastTimeModified($file);

                craft()->assets->storeFile($fileModel);

                // print_r($fileModel);

                // displaying file
                $image = array(
                    'url' => 'images/'.$filename,
                    'id' => 1
                );
                $this->returnJSON($image);
                exit;
            }
            else
            {
                $errors[] = "$filename was unable to be saved.";
            }
        }
    }

    $this->returnJSON(compact('errors'));
    exit;
}

}

How do I get my form to talk to it? Also, what else do I need to do to get it to work?

It doesn't seems possible natively, you should write a custom upload script.

→ Example #1

→ Example #2

If it doesn't matter to add the images inside your rich text field, one more simple workaround could be to allow image upload to your assets using a separate upload field.

→ Uploading Files from Front-end Entry Forms


Craft Commerce Shipping Total Order Price rule I have a webshop where you can get free shipping when the minimum total order price is €150.
Product prices are set up so they include VAT (21%).
VAT is removed when orders are shipped outside the Netherlands.
In most scenarios shipping cost calculation is not a problem but there is one VAT-related  specific scenario where it is not working.

Let's begin with the scenario that works as expected:

1) User buys product(s) which include VAT and the total order amount is  €151. Shipping address is inside EU so he is correctly eligible for free shipping.

Now lets go to the scenario where it does not work:

2) User buys the same product(s) as above and the total order amount is again €151. User is again eligible for free shipping but this time shipping is outside the Netherlands. That means that VAT is being excluded and therefore the final amount that user has to pay is below €150 and therefore he should pay for the shipping. But this is not happening.

It seems that system reads the 'total order price' as the total amount of the order before the tax reduction is applied. Therefore, according to the system user is eligible for free shipping. Though this is not correct.

My question is: Is there any way to make system look at the "final" total amount so the shipping calculation is correct?

The current rule for the total in Commerce 1 is in craft/plugins/commerce/models/Commerce_ShippingRuleModel.php starting at line 214:

if ($this->minTotal && $this->minTotal > $order->itemTotal)
{
    return false;
}
if ($this->maxTotal && $this->maxTotal <= $order->itemTotal)
{
    return false;
}

Try changing it to use totalPrice and see if that resolves the issue for you:

if ($this->minTotal && $this->minTotal > $order->totalPrice)
{
    return false;
}
if ($this->maxTotal && $this->maxTotal <= $order->totalPrice)
{
    return false;
}

If we were to go ahead and change it in core, it would be a breaking change for other users. The only way around that is to make a new setting.

If it resolves the issue for you, I will look into making the new setting.