Problem/Motivation

Using simple twig filters with a pipe dont work, but wrapping with a {% filter foo %} "kinda" does

examplate in themes/classy/templates/field/field--node--title.html.twig
{{ item.content|upper }}
throws an error:

Warning: mb_strtoupper() expects parameter 1 to be string, array given in twig_upper_filter() (line 1276 of vendor/twig/twig/lib/Twig/Extension/Core.php).

but using

{% filter upper %}
    {{ item.content }}
{% endfilter %}

everything (almost) works as expected when the filter block is used as a function

If theres html inside of it using {% filter upper %}will result in outputting markup as escaped tags
<P>LOUD &AMP; NOISE </P>

even more interesting is if i want to remove markup that a wysiwyg editor have edited and use

      {% filter striptags %}
        {{ item.content }}
      {% endfilter %}

special characters like &amp; is converted.

taking it one step further and go raw on the item.content

  {% filter upper %}
    {{ item.content|raw }}
  {% endfilter %}

Do we really want ppl to do |raw on the strings, but yeah that will happen if thats the only way.

Proposed resolution

Make string manipulation possible using drupal OR update the docs https://www.drupal.org/node/2357633 and tell and make it clear that themers cant be trusted to do string manipulation that everybody else that uses twig can http://twig.sensiolabs.org/doc/templates.html#filters

Remaining tasks

User interface changes

API changes

Data model changes

CommentFileSizeAuthor
#12 kint-dump.png47.83 KBmortendk
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mortendk created an issue. See original summary.

mortendk’s picture

Title: twig string filters dont work ? » twig string filters dont work.
Issue summary: View changes
mortendk’s picture

Issue summary: View changes
mortendk’s picture

msankhala’s picture

Issue summary: View changes
mortendk’s picture

Issue summary: View changes
mortendk’s picture

Issue summary: View changes
star-szr’s picture

This is because you are trying to run a string filter on a render array which is not possible. Agreed docs could be better but you need to |render the array first before you run other filters :)

mortendk’s picture

{{ item.content|render|upper }} still gives me escaped formatted html
<P>LOUD &AMP; NOISE </P> so its kinda back to the same issue of "not really working" ;)

Even more interesting if i wanna strip out tags from a string (lets say i wanna use it for some data-attribute something and i do a {{ item.content|render|striptags }} then an & gets printed out as & - which isnt really whats expected.

So even with |render|filter im still not getting what is expected, and that will force me onto a quest of "getting my data the way i want" -> lets see where i can poke (finding the frontend stick of epic-poke-making-security-issues-nobody-thought-about *evil laughter*

mortendk’s picture

i have added to the documentation to use {{ item|render|filter }}to avoid the confusion.
We might gonna make it very explicit to people that everything is autoescaped, so if you want to manipulate a string you cant really do it if an enduser have added the data in as html in anyway.

star-szr’s picture

It sounds then like item.content is not marked as safe, not sure what type of value it is. kint(item.content) or dump(item.content) might be worth a peek.

mortendk’s picture

FileSize
47.83 KB

in this case its a text field with potential html text inside of it (why i in the first place wanted to remove that before i added it into the link so i could use it for a tool til and an data attribute
ala :

<a href=""
data-tooltip="{{ content.item|render|striptags }}
>{{foo}} </a>

kint dump

star-szr’s picture

Okay I see what you mean now. We may have to consider whether some filters can create a new Markup object but there would have to be limits there I think.

To get what you want in your case I think you could do {{ item.content['#text']|striptags }}

Edit: To give more background I forgot this morning when replying that rendering returns a Markup object. Once you print and manipulate that string it's no longer safe, that's why it's getting escaped.

joelpittet’s picture

It would be nice to preserve safeness on some filters, but the manipulation *could* open a security hole. I tested with striptags and it was hard to crack, but maybe that's just time and patience. A bit hesitant to recommend |raw, but if I knew where the source was coming from, I'd be likely using that, but like the Issue summary says,

Do we really want ppl to do |raw on the strings, but yeah that will happen if thats the only way.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Pranali.addweb’s picture

In my case filters are working very well without using filter block. For example, if we use capitalize filter it will return first value with an uppercase. Let me explain it as an example. My problem gets resolved with this, as we can try it for a better approach.

{% set var = 'Hello Testing' %}

{# Print in UPPERCASE #}
{{ var|upper }} 

OUTPUT--> {# 'HELLO TESTING' #}

Apart from upper there are few other filters are also available to modify the capitalization, We should try them for a better approach and modify capitalization style of our strings.

<ul>
  {# Set test strings #}
  {% set strLower = 'this is for test' %}
  {% set strUpper = 'THIS IS FOR TEST' %}
  {% set strMixed = 'this Is for TEST' %}

  {# Apply Twig filters #}
  <li>upper: {{ strLower|upper }}</li> {# 'THIS IS FOR TEST' #}
  <li>lower: {{ strUpper|lower }}</li> {# 'this is for test' #}

  {# Apply filters provided by Craft #}
  <li>ucwords: {{ strLower|ucwords }}</li> {# 'This Is For Test' #}
  <li>ucfirst: {{ strLower|ucfirst }}</li> {# 'This is for test' #}
  <li>lcfirst: {{ strUpper|lcfirst }}</li> {# 'tHIS IS FOR TEST' #}      

  {# Combine filters for predictable application #}
  <li>ucwords: {{ strMixed|lower|ucwords }}</li> {# 'This Is For Test' #}
  <li>ucfirst: {{ strMixed|lower|ucfirst }}</li> {# 'This is for test' #}
  <li>lcfirst: {{ strMixed|upper|lcfirst }}</li> {# 'tHIS IS FOR TEST' #}

  {# Examples for possible use case #}
  <li>PascalCase: {{ strMixed|lower|ucwords|replace(' ', '') }}</li> {# 'ThisIsForTest' #}
  <li>camelCase: {{ strMixed|lower|ucwords|lcfirst|replace(' ', '') }}</li> {# 'thisIsForTest' #}
</ul>

Hope this helps you.

joelpittet’s picture

Status: Active » Closed (outdated)

I'm going to close this, but thanks for the extra help showing @dharmdeep.addweb.

Stephen Ollman’s picture

Not sure if this will help anyone, but the following fixed my issue.

Changed in the theme page.html.twig

{% if page.sidebar_first|trim %}

to

{% if page.sidebar_first|render|trim %}

snable’s picture

THX, made my day!

However, i cannot figure out why e.g. the piped trim filter does not work without the additional piped render filter.

Tunprog’s picture

This worked for me thanks:

<h2 id="{{ item.content|render|replace({' ': '-'}) }}">Hello</h2>