Twig search with multiple parameters - php

We are making a website with a search form. In that form users can search with text and checkboxes. With the checkboxes users can search only in the related categories.
We need to accomplish this with Craft CMS and Twig.
We tried the following method, but that didnt worked.
{% set query = craft.request.getParam('search-results') %}
{% set nietBijdragePlichtig = craft.request.getParam('plg-Nee') %}
{% if nietBijdragePlichtig == 'on' %}
{% for entry in craft.entries.section('producten').limit(null).order(asc).search('query, nietBijdragePlichtig').find() %}
<div id=”test”>test</div>
{% endfor %}
{% endif %}
and we tried:
{% set query = craft.request.getParam('search-results') %}
{% set nietBijdragePlichtig = craft.request.getParam('plg-Nee') %}
{% set alle = query ~ ' ' ~ nietBijdragePlichtig %}
{% if nietBijdragePlichtig == 'on' %}
{% for entry in craft.entries.section(‘producten’).limit(null).order(asc).search(alle).find() %}
<div id=”test”>test</div>
{% endfor %}
{% endif %}
We also tried to use multiple .search()
We tried both codes with different syntaxes.
How can we accomplish this?
Really thanks!

Related

twig merge error Unexpected token "punctuation" of value "["

My goal is having a string like "name: smoothie, ingredients: milk, orange, category: vegan" (there can be a lot option: value or option: value, value, value... pairs) to produce an array like the following
[
{
option: 'name',
value: ['smoothie']
},
{
option: 'ingredients',
value: ['milk', 'orange']
},
{
option: 'category',
value: ['vegan']
}
]
I thought something like the following would work but it produces the following error and i can't understand why.
The problem is in the line where i try to add a value to the existing options[last_ok_index].value array
{% set options[last_ok_index].value = options[last_ok_index].value|merge( [ x[0] ] ) %}
Unexpected token "punctuation" of value "[" ("end of statement block" expected).
{% set product = "name: smoothie, ingredients: milk, orange" %}
{% set options = [] %}
{% set last_ok_index = 0 %}
{% for item in product|split(',') %}
{% set x = item|split(': ') %}
{% if x|length == 2 %}
{% set options = options|merge( [ { option: x[0], value: [x[1]] } ] ) %}
{% set last_ok_index = loop.index - 1 %}
{% else %}
{% set options[last_ok_index].value = options[last_ok_index].value|merge( [ x[0] ] ) %}
{% endif%}
{% endfor %}
{# print result #}
{% for item in options %}
{{item.option }}
{% for inner_item in item.value %}
{{"-" ~ inner_item}}
{% endfor %}
{% endfor %}
You should go with the suggestion in the comments by #dbrumann and use a TwigExtension.
However if you want to solve this in pure twig, then you are overcomplicating things.
First things first, the problem already starts at your first split, your expected output is smoothie and ingredients, while the actual result will be smoothie, ingredients, orange. You can fix this by passiung asecond argument to the split filter, which will limit the output.
Split uses the PHP function explode in the background. More on what the second parameters does you can find in the documentation here
Now as I said you can simply your snippet by creating the "item" in two parts rather than one part
{% set product = "name: smoothie, ingredients: milk, orange" %}
{% set items = [] %}
{% for item in product|split(',', 2) %}
{% set tmp = item|split(':') %}
{% set option = tmp[0] %}
{% set values = [] %}
{% for value in tmp[1]|split(',') %}
{% set values = values|merge([ value, ]) %}
{% endfor %}
{% set items = items|merge([ {'option': option, 'values': values,}, ]) %}
{% endfor %}
demo
As you've changed the initial input of the original question. The problem still starts with the split filter. I'd suggest you use another delimeter for your values, e.g. ;
{% set product = 'name: smoothie 3, ingredients: milk ; orange; pineapple, category: bar' %}
{% set products = [] %}
{% for string in products_raw %}
{% set product = [] %}
{% for item in string|split(',') %}
{% set tmp = item|split(':') %}
{% set option = tmp[0] %}
{% set values = [] %}
{% for value in tmp[1]|split(';') %}
{% set values = values|merge([ value, ]) %}
{% endfor %}
{% set product = product|merge([ {'option': option, 'values': values,}, ]) %}
{% endfor %}
{% set products = products|merge([ product, ]) %}
{% endfor %}
{% for product in products %}
{% for item in product %}
- Option: {{ item.option }}
- Values:
{% for value in item.values %}
- {{value }}
{% endfor %}
{% endfor %}
----------------------------------
{% endfor %}
demo
Thank you a lot for all the tips, i changed the logic a bit and it works now.
I will search about twig extensions as you proposed since it is for sure too much code in twig for something like that.
{% set product = "name: smoothie, ingredients: milk, orange, sugar, tags: healthy, popular, category: milk" %}
{% set options = [] %}
{% set last_option = null %}
{% set last_value = null %}
{% for item in product|split(',') %}
{% set x = item|split(':') %}
{% if x|length == 2 %}
{% if last_value|length > 0 %}
{% set options = options|merge( [ {option: last_option, value: last_value} ] ) %}
{% endif %}
{% set last_option = x[0] %}
{% set last_value = [x[1]] %}
{% else %}
{% set last_value = last_value|merge([x[0]]) %}
{% endif%}
{% if loop.last %}
{% if last_value|length > 0 %}
{% set options = options|merge( [ {option: last_option, value: last_value} ] ) %}
{% endif %}
{% endif %}
{% endfor %}
{# print result #}
{% for item in options %}
{{ item.option }}
{% for inner_item in item.value %}
{{ "-" ~ inner_item }}
{% endfor %}
{% endfor %}

How to render twig condition dynamically from php array

How to render twig condition dynamically from php array
Php data array
arry('label'=>'test','parentRoleExp'=>"is_granted('ROLE_ADMIN') OR is_granted('ROLE_BLOG')"
twig code
{% set parentRoleExp = '' %}
{% if link['parentRoleExp'] is defined %}
{% set parentRoleExp = link['parentRoleExp'] %}
{% endif %}
{% if parentRoleExp %}
<h1>Admin Blog</h1>
{% else %}
<h1>Blog <?h1>
{% endif %}
Above code not working
Expected result
{% if is_granted('ROLE_ADMIN') OR is_granted('ROLE_BLOG') %}
<h1>Admin Blog</h1>
{% else %}
<h1>Blog <?h1>
{% endif %}
I tried with various method but not working. please help
Thanks in advance
it's very bad idea - ulnerability
But if you want... register eval() function:
$twig = new Twig\Environment($loader);
$twig->addFunction(new Twig\TwigFunction('phpEval', 'eval'));
in template
{% if phpEval(parentRoleExp) %}

Find value in array and return with new from different array

Currently I have two arrays
{% set code = [AMS, EIN, RTM] %}
{% set city = [Amsterdam, Eindhoven, Rotterdam] %}
I would like to check if the value of {{airport}} exists in the first array and if it is code[0] I would like to change {{airport}} into the value of city[0]. Is this possible with Twig?
You can loop over the code array:
{% for c in code %}
{# ... #}
{% endfor %}
Documentation: https://twig.symfony.com/doc/2.x/tags/for.html
Then if the item does match:
{# ... #}
{% if airport == c %}
{# ... #}
{% endif %}
{# ... #}
Documentation: https://twig.symfony.com/doc/2.x/tags/if.html
Replace the variable airport, at the same loop index:
{# ... #}
{% set airport = city[loop.index0] %}
{# ... #}
Documentation: https://twig.symfony.com/doc/2.x/tags/for.html#the-loop-variable
So, in full:
{% for c in code %}
{% if airport == c %}
{% set airport = city[loop. index0] %}
{% endif %}
{% endfor %}
Running fiddle: https://twigfiddle.com/xflfas/2
Out of the scope note: your arrays would be better named cities and codes.
This way, when you loop over them, you end up with meaningful naming
{% set codes = ['AMS', 'EIN', 'RTM'] %}
{% for code in codes %}
{{ code }}
{% endfor %}
{# and #}
{% set cities = ['Amsterdam', 'Eindhoven', 'Rotterdam'] %}
{% for city in cities %}
{{ city }}
{% endfor %}
Use {% if value in array %} to search from the first array and Twig's merge function to replace the value in the second array. See this https://twig.symfony.com/doc/2.x/filters/merge.html

How to set a custom class to submenus in Drupal 8?

I am working on sidebar menu in a Custom Drupal 8 Theme. I am trying to set a class of sidebar__menu--submenu-1,sidebar__menu--submenu-2, sidebar__menu--submenu-3 and so on depending on the submenu's level.
So far, I was able to add the class sidebar__menu to the first level & sidebar__menu--submenu to all submenu's level. However, I want to add the 'class' sidebar__menu--submenu-(number of the level) so I can style & control the sidebar better with CSS.
Here it is my code menu.html.twig:
{{ menus.menu_links(items, attributes, 0) }}
{% macro menu_links(items, attributes, menu_level, menu_name) %}
{% import _self as menus %}
{%
set menu_classes = [
'sidebar__menu' ~ menu_name|clean_class,
]
%}
{%
set submenu_classes = [
'sidebar__menu' ~ menu_name|clean_class ~ '--submenu',
]
%}
{% if items %}
{% if menu_level == 0 %}
<ul{{ attributes.addClass('container mx-auto', menu_classes) }}>
{% else %}
<ul {{ attributes.removeClass(menu_classes).addClass(submenu_classes) }}>
{% endif %}
{% for item in items %}
{%
set classes = [
'sidebar__item',
item.is_expanded ? 'sidebar__item--expanded',
item.is_collapsed ? 'sidebar__item--collapsed',
item.in_active_trail ? 'sidebar__item--active-trail',
]
%}
<li{{ item.attributes.addClass(classes) }}>
{{ link(item.title, item.url) }}
{% if item.below %}
{{ menus.menu_links(item.below, attributes, menu_level + 1) }}
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
{% endmacro %}
Any help will be really appreciate it!
I have found the answer. First we set the classes:
{%
set submenu_classes = [
'sidebar__menu' ~ menu_name|clean_class ~ '--submenu',
'sidebar__menu--submenu-' ~ (menu_level + 1),
]
%}
Then using the logic like so:
{% if menu_level == 0 %}
<ul{{ attributes.addClass('container mx-auto', menu_classes) }}>
{% else %}
<ul{{ attributes.removeClass(menu_classes, 'sidebar__menu--submenu-' ~ (menu_level)).addClass(submenu_classes) }}>
{% endif %}

Print Twig variable x times based upon randomized range

I am using Twig and Timber for a WordPress project. I have the following loop in my template that prints my custom post type titles into a HTML structure.
{% for company in companies %}
{% set dot = "<div class='company-dot'></div>" %}
{% set range = range(10, 20) %}
{{dot}}
{{random(range)}}
<div class="company">
<div class="company-dot dot-active"></div>
<p class="dot-caption">{{ company.title }}</p>
</div>
{% endfor %}
I would like to print my {{dot}} variable x amount of times based upon the number that is generated by {{random(range)}}. How can I do this?
The simplest solution would be to iterate random(range) times with a for loop:
{% for i in 0..random(range(10, 20)) %}
{{ dot }}
{% endfor %}
I don't really know Twig but my guess is that you could to the following:
{% for i in random(range) %}
{{dot}}
{% endfor %}
You already know how to use range, just use it again :
{% set dots_count = random(range) %}
{% for dot_index in range(1,dots_count) %}
{{dot}}
{% endfor %}
{{dots_count}}
Here is a fiddle : https://twigfiddle.com/ko595z

Categories