Twig: how to set object variable? - twig

I try to create new variable from exists object variable in Twig template (filter is object):
{% for filter in filters %}
{% if filter.type != 'selectImage' %}
{{ filter.render()|raw }}
{% elseif filter.type == 'selectImage'%}
{% set selectFilter = filter %}
{% endif %}
{% endfor %}
but i get error:
Catchable fatal error: Object of class Filters\Filter could not be converted to string in vendor\twig\twig\lib\Twig\Environment.php(403) : eval()'d code on line 40
on
{% set selectFilter = filter %}
How i can set object to new vairable?

According to the official TWIG documentation, filter is the name of a tag in TWIG language.
You should rename your variable in your code to avoid problems in the generated PHP code:
{% set selectFilter = myFilter %}

Related

Check if all elements in one array are contained by another | JS Array.every() equivalent

I'm looping over a collection of blog posts (Twig for loop) which appearance depends on tags given.
Here a quick example: I want to display all blog posts that have the tags "foo" and "bar".
It seems pretty easy to check if a post has one of the tags.
However it seems that checking if both tags are contained by a blog post isn't trivial.
What I want to accomplish is what the array.every() method in javascript does.
That's my current solution which works as expected but feels kinda fiddly and overcomplicated:
{% set given_tags_array = data.tags|split(',') %}
{% for post in posts %}
{% set post_categories_array = post.categories|map(category => category.name) %}
{% set bool_buffer_array = [] %}
{# push comparison result in bool array #}
{% for tag in given_tags_array %}
{% set bool_buffer_array = bool_buffer_array|merge([tag in post_categories_array]) %}
{% endfor %}
{# only display posts where all tags match #}
{% if false in bool_buffer_array %}
{% else %}
{# post data goes here #}
{% endif %}
{% endfor %}
As you can see inside the posts loop I'm checking if every given tag (i.e. "foo" and "bar") is part of the post categories array. I'm pushing the comparison result (boolean) to an empty array to check for any false values afterwards.
Why an array? I tried using a simple boolean variable but if any of the given tags is in the post categories array it resolves to true, which isn't exactly what I want.
So something like that doesn't work for me unfortunately:
{% for post in posts %}
{% set post_categories_array = post.categories|map(category => category.name)|sort|join('') %}
{% if given_tags_array|filter(given_tag => given_tag in post_categories_array) %}
{# post data goes here #}
{% endif %}
{% endfor %}
With this method I'm always doing an or comparison instead of an and comparison...
So...am I missing something and is there a simpler way to do that twig only?
Using the code you've already provided:
{% set temp = given_tags_array|filter(given_tag => given_tag in post_categories_array) %}
The filter filter returns a new array, this means temp should contain as many elements as your given_tags_array, if they are all inside the post_categories_array.
So if I'm not mistaken you could change your check to the following
{% for post in posts %}
{% set post_categories_array = post.categories|map(category => category.name)|sort|join('') %}
{% set temp = given_tags_array|filter(given_tag => given_tag in post_categories_array) %}
{% if temp|length == given_tags_array|length %}
{# display post #}
{% endif %}
{% endfor %}

Twig strip textarea and create array

I'm trying to strip some text from a value and afterwards create an array from it with the stripped values.
I'm having troubles to strip the text value.
I can only do this on the frontend since I have no access to the backend (SaaS platform)
In below example value.value (originally a textarea) returns the following text:
[185047078]1x something - Type 1
[415533322]1x something - something
[152890667]1x something 500x500 mm
I want to strip the text so I have [185047078], [415533322], [152890667] left or without the brackets.
Normally in JS you would do something like:
hide_ids = txt.match(/[^\]\[]+(?=\])/g)
However it need to be done in Twig.
Afterwards I want to push the values into an array hide_ids.
{% set hide_ids = [] %}
{% if product.custom %}
{% for custom in product.custom %}
{% if 'Some title' in custom.title %}
{% for value in custom.values %}
{% set hide_this_id = value.value %}
{% if hide_this_id matches '{/[^\]\[]+(?=\])/g}' %}
{% set hide_ids = hide_ids | merge([hide_this_id]) %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
{% set hidden = false %}
{% if id in hide_ids %}
{% set hidden = true %}
{% endif %}
What is the equivalent of match in Twig? I also tried replace but I just can't get that text stripped.
Any help greatly appreciated!
You could go with some simple string functions.
{% for id in ids %}
{{ id | split(']', 2)[0] | replace({'[': '',}) }}
{% endfor %}
demo
split is the explode of twig. This will separate your string in chased based on the ] character. The 2nd parameter (2) ensures there will only be maximum 2 parts in the array.
replace is just str_replace
If you wanted to solve this with regex you would either need to write a function/filter with preg_match or install an extension like this

Twig replace part of string with chosen character

I want to replace part of string characters with asterisks in Twig.
For example:
SomePartlyVisibleStringHere
I want to change every letter after 4th in this string with asterisks, to have result like that:
Some*********************
Is it possible to do without defining new Twig helper?
You could make a macro (a function in Twig) and call it whenever you want to do this.
{% macro redact(topSecret) %}
{% set length = topSecret|length - 4 %}
{{ topSecret|slice(0, 3) }}{% for i in 0..length %}*{% endfor %}
{% endmacro %}
{# You have to import from _self if the macro is declared in the same file. #}
{% import _self as sharpie %}
{{ sharpie.redact('Top secret information') }}
{# => Top******************* #}
Example: https://twigfiddle.com/aobt8s
This worked for me:
{% set string = 'SomePartlyVisibleStringHere' %}
{% set starCount = string|length - 4 %}
{{ string[:4] }}{% for i in 1..starCount %}*{% endfor %}
If you have to do it more than once I would suggest making a custom filter, then you can just do:
{% set string = 'SomePartlyVisibleStringHere' %}
{{ string|customFilterName }}

I want to genrate dynamic variable in TWIG and fetch value

i want to set dynamic variable and get value of that variable. I had pass "orderDetails" to my twig template.
$customerProfile = array(
'ns1' => $customerProfile->getNs1(),
'ns2' => $customerProfile->getNs2(),
'custId' => $customerProfile->getCustId()
)
return $this->render('PortalBundle::popup.html.twig', array(
'orderDetails' => $customerProfile
));
get that variable like {{orderDetails.ns1}}, {{orderDetails.ns2}} like this but i have 15 to 16 variable like this and i want to fetch this variable in loop.
i have code for this like
{% for i in 1..13 %}
{% set nsOrd = 'orderDetails.ns'~i %}
{% if nsOrd %}
{{nsOrd}}
{% endif %}
{% endfor %}
i want to fetch variable {{orderDetails.ns1}} and other. Give me your suggestion.
thanks Yoshi, I have hundered of variable in array. thanks for support, i have found and successfully get output using this.
{% for i in 1..13 %}
{% if orderDetails['ns' ~ i] is defined %}
{{orderDetails['ns' ~ i]}}
{% endif %}
{% endfor %}

Scope of variable in jinja2 template

I am writing jinja2 template based application. I am trying to write a logic to set variable.
{% set last_item = none %}
{% for u in users %}
{% if not u.username == user.username%}
{% if g.user.is_bestfriend(u) %}
{% set last_item = 'true' %}
{% endif %}
{% endif %}
{% endfor %}
{{last_item}}
but after {% endfor %}, last_item value is again set to none, instead of true. Is there any way to set it to true in jinja2 template?
Since version 2.10 you can do this using a namespace variable, set before entering the scope:
{% set ns = namespace(found=false) %}
{% for item in items %}
{% if item.check_something() %}
{% set ns.found = true %}
{% endif %}
* {{ item.title }}
{% endfor %}
Found item having something: {{ ns.found }}
See also the documentation: http://jinja.pocoo.org/docs/2.10/templates/#assignments
Due to scoping rules in jinja2, you cannot access a variable outside the scope that it was set in. Sorry :(

Resources