How would you do ternary conditionals inside {%%} in Twig - php

I want to render parameters if they exist but can't find a way of correctly displaying it and keep getting
An opened parenthesis is not properly closed. Unexpected token "punctuation" of value ":" ("punctuation" expected with value ")")
where
{% setcontent records = 'properties' where
{filter:search_term,
((classification) ? ('classification':classification):(''))
} printquery %}

To use it inside Bolt CMS, first define your options and then pass that to Bolt CMS
{% set options = { filter: search_term , } %}
{% if classification is defined and classification|trim != '' %}
{% set options = options|merge({classification:classification,}) %}
{% endif %}
{% setcontent records = 'properties' where options printquery %}
After rereading your question you are probably looking for something like this,
{% set records %}
'properties' where {
filter : '{{ search_term }}',
classification: '{{ classification is defined ? classification : '' }}',
} printquery %}
{% endset %}
{{ records }}
However using the filter default here is more suited than using the ternary operator,
{% set records %}
'properties' where {
filter : '{{ search_term }}',
classification: '{{ classification|default('') }}',
} printquery %}
{% endset %}
{{ records }}
demo
To omit properties you would use the following,
{% set records %}
'properties' where {
filter : '{{ search_term }}',
{% if classification is defined and classification|trim != '' %}classification: '{{ classification }}',{% endif %}
} printquery %}
{% endset %}

Related

BoltCMS fetch content filters by taxonomies

trying to achieve needed behaviour with Bolt CMS content types, but can't, so asking for help
Have Content Type and 2 taxonomies, industries_t and services_t
{% set condition = condition|merge({'industries_t' : industriesFilter|join(' || ')}) %}
{% endif %}
{% if topicsFilter is not empty %}
{% set condition = condition|merge({'services_t' : topicsFilter|join(' || ')}) %}
{% endif %}
{% if app.request.query.get('from') is not empty or app.request.query.get('to') is not empty %}
{% set fromFilter = app.request.query.get('from') is not empty ? app.request.query.get('from') : '2014-01-01' %}
{% set toFilter = app.request.query.get('to') is not empty ? app.request.query.get('to') : 'now'|date('Y-m-d') %}
{% set condition = condition|merge({'publishedAt' : '\>' \~ fromFilter \~ ' && \<' \~ toFilter }) %}
{% endif %}
{% if app.request.query.get('search') is not empty %}
{% set condition = condition|merge({'title' : '%' \~ app.request.query.get('search') \~ '%' }) %}
{% endif %}
{% setcontent casestudies = 'case-studies' where condition orderby "-publishedAt" limit 6 %}
I need to fetch records, that has ´"industries_t" = "Test" OR services_t = "Another"´
right now, it works like "SELECT records where industries_t = "Test" and services_t = "Another"
is there any way to make it "SELECT records where industries_t = "Test" OR services_t = "Another"?

Merge key and value into an array in Twig file

I want to add key and value into array in twig file. But I am facing following issue "Twig_Error_Syntax: A hash key must be a quoted string or a number"
{% set phoneCount = 0 %}
{% set phoneNumbers = {} %}
{% for currPhone in currBroker.phones %}
{% if (currPhone.type == 'Work' or currPhone.type == 'Mobile') and phoneCount <= 2 and currPhone.number !='' %}
{% set phoneCount = phoneCount + 1 %}
{% set phoneNumbers = phoneNumbers|merge({ currPhone.type:currPhone.type }) %}
{% endif %}
{% endfor %}
{{ phoneNumbers|print_r }}
I just need the syntax of merging key and value into array.
I tried by giving static inputs and its works
{% set phoneNumbers = phoneNumbers|merge({ 'work':'(011)112-1233' }) %}
But its not working for dynmic input. Please help!!
You have to wrap your key in braces :
{% set phoneNumbers = phoneNumbers|merge({ (currPhone.type) : currPhone.type }) %}
Tested and working example :
{% set currPhone = {type: 'test'} %}
{% set phoneNumbers = {} %}
{% set phoneNumbers = phoneNumbers|merge({ (currPhone.type) : currPhone.type }) %}
{% dump(phoneNumbers) %}
I get :
array:1 [▼
"test" => "test"
]

twig dynamic variable call

I passed data in 3 languages to the twig template and display this data in this way:
{% set lang=app.request.get("lang")%}
{% for item in contests%}
{% if lang=="fa"%}
{{item.titlefa}}
{% elseif lang=="en"%}
{{item.titleen}}
{% elseif lang=="ar"%}
{{item.titlear}}
{% endif%}
{% endfor%}
It is wirking but I must create 3 if condition for each object in "contests"
How can i show data in this logic:
{% set lang=app.request.get("lang")%}
{{item.title~lang}}
{% endfor%}
that can call proper method in contest
You can use the attribute TWIG function for call at runtime a method name, as example:
{% set lang=app.request.get("lang")%}
{% methodname = 'title'~lang %}
{% for item in contests%}
{{ attribute(item, methodname) }}
{% endfor%}
Hope this help

Is there any way to get average values from an array when using a Twig template?

Is there any way of getting the average value of an array of value just inside a Twig template when using Symfony2?
I tried something like the following code but it doesn't work
{% set sumratings = 0 %}
{% set count = 0 %}
{% for rating in article.ratings %}
{% set sumratings = sumratings + rating.value %}
{% endfor %}
AVG: {{ sumratings / article.ratings.count }}
Any idea?
I think this should do it
{% set sumratings = 0 %}
{% for rating in article.ratings %}
{% set sumratings = sumratings + rating.value %}
{% endfor %}
AVG: {{ sumratings / article.ratings|length }}
Assuming rating.value is an integer
There is no built-in way to do that. Creating your own twig extension that can do it is simple! You need to create a filter, which is very well doumented in the cookbook: How to write a custom Twig Extension.
The answer is correct but horrible to use, right ?
It's simple:
function arrayAverage($array)
{
if (!is_array($array)) return false;
if (!count($array)) return 0;
$avg=0;
foreach ($array as $num) $avg+=$num;
$avg/=count($array);
return $avg;
}
$twig->addFilter('arrayAverage', new Twig_Filter_Function('arrayAverage'));
Now you can just do like this in your twig templates:
{{ somearray | arrayAverage }}
{{ somearray | arrayAverage | number_format }}
In modern Twig versions, there's a reduce() filter that can simplify this work, a bit:
{% set myValues = [1, 2, 3, 4, 5] %}
{% set average = (myValues | reduce((sum, val) => sum + val, 0)) / (myValues | length) %}
{{ average }} {# 3 #}
See this fiddle!

Setting element of array from Twig

How can I set member of an already existing array from Twig?
I tried doing it next way:
{% set arr['element'] = 'value' %}
but I got the following error:
Unexpected token "punctuation" of value "[" ("end of statement block"
expected) in ...
There is no nice way to do this in Twig. It is, however, possible by using the merge filter:
{% set arr = arr|merge({'element': 'value'}) %}
If element is a variable, surround it with brackets:
{% set arr = arr|merge({(element): 'value'}) %}
I ran into this problem but was trying to create integer indexes instead of associative index like 'element'.
You need to protect your index key with () using the merge filter as well:
{% set arr = arr|merge({ (loop.index0): 'value'}) %}
You can now add custom index key like ('element'~loop.index0)
If initialization only need:
{% set items = { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'unknown' } %}
I have tried #LivaX 's answer but it does not work , merging an array where keys are numeric wont work ( https://github.com/twigphp/Twig/issues/789 ).
That will work only when keys are strings
What I did is recreate another array ( temp) from the initial array (t) and make the keys a string , for example :
{% for key , value in t%}
{% set temp= temp|merge({(key~'_'):value}) %}
{% endfor %}
t keys : 0 , 1 , 2 ..
temp keys : 0_, 1_ , 2_ ....
You can also use the following syntax:
{% set myArray = myArray + myArray2 %}
Just use this like {% set arr={'key':'value'} %} (with no blank space after the :), it works well.
But when I use it inside a for loop, to make it an array, it does not work outside of the for scope.
{% for group in user.groups %}
{% set foo={'loop.index0':'group.id'} %}
{% set title={'loop.index0':'group.title'} %}
{{ title }} //it work
{% else %}
{% set foo={'0':'-1'} %}
{% set title={'0':'未分组'} %}
{% endfor %}
{{ title }} //it does not work, saying title is not defined
{% set links = {} %}
{# Use our array to wrap up our links. #}
{% for item in items %}
{% set links = links|merge({ (loop.index0) : {'url': item.content['#url'].getUri(), 'text': item.content['#title']} }) %}
{% endfor %}
{%
set linkList = {
'title': label,
'links': links
}
%}
{% include '<to twig file>/link-list.twig'%}
Thanks for this thread -- I was also able to create an array with (loop.index0) and send to twig.
I've found this issue very annoying, and my solution is perhaps orthodox and not inline with the Twig philosophy, but I developed the following:
$function = new Twig_Function('set_element', function ($data, $key, $value) {
// Assign value to $data[$key]
if (!is_array($data)) {
return $data;
}
$data[$key] = $value;
return $data;
});
$twig->addFunction($function);
that can be used as follows:
{% set arr = set_element(arr, 'element', 'value') %}
Adding my answer in case anyone needs to update the array when merge doesn't work because it just appends to the end of an array instead of providing the ability to change an existing value.
Let's say you have an array words_array like below:
Object {
0: "First word"
1: "Second word"
2: "Third word"
}
In order to update "Second word", you can do the following:
{% set words_array = {(1): 'New word'} + words_array %}
The resulting array would be:
Object {
0: "First word"
1: "New word"
2: "Third word"
}
You can take it one step further if you are using a loop and use the loop.index0 variable something like the following:
{% for word in words_array %}
{% if word == 'Second word' %}
{% set words_array = {(loop.index0): 'New word'} + words_array %}
{% endif %}
{% endfor %}
You can declare the array as follows
{% set arr = [{'element1': 'value1','element2' : 'value2'},{'element1': 'value1','element2' : 'value2'},{'element1': 'value1','element2' : 'value2'}] %}
I had a multi dimension array. The only solution I could find out is create a new temporary array and update/add the information, which was further passed on to another twig function.
I had this problem sometime ago. Imagine you have an array like this one:
data = {
'user': 'admin',
'password': 'admin1234',
'role': 'admin',
'group': 'root',
'profile': 'admin',
'control': 'all',
'level': 1,
'session': '#DFSFASADASD02',
'pre_oa': 'PRE-OA',
'hepa_oa': 'HEPA-OA',
'pre_ra': 'HEPA-RA',
'hepa_ra': 'HEPA-RA',
'deodor_ra': 'DEODOR-RA'
}
So, you want to show this data in two rows, but remove the password from that list. To this end, split in 2 arrays will be easy with the slice filter. However, we have to remove the password. For that reason, I'm using this snippet. The idea is to put all the elements lesser than the data elements size divided by 2. To calculate this we use the filter length. Now to get the index of the current element we user loop.index. And finally we *push an associative element in the left or right array. An associative array has two components key and value. To reference an array key in twit we operator () and we use the merge filter to push into the array as shown here {% set left_list = left_list|merge({ (key): value }) %}
This is the complete solution.
{% set left_list = {} %}
{% set right_list = {} %}
{% set limit = data|length // 2 %}
{% for key, value in data|cast_to_array %}
{% if key != 'password' %}
{% if loop.index <= limit %}
{% set left_list = left_list|merge({ (key): value }) %}
{% else %}
{% set right_list = right_list|merge({ (key): value }) %}
{% endif %}
{% endif %}
{% endfor %}
{% for key, value in left_list %}
<p>
<label for="{{key}}">{{key}}</label>
<input type="text" name="{{key}}" id="{{key}}" value="{{value}}"
class="text ui-widget-content ui-corner-all">
</p>
{% endfor %}

Categories