Find if twig array is empty of non-protected values - php

Given an a php array in a twig template:
object(Drupal\Core\Template\Attribute)#1208 (1) {
["storage":protected]=> array(0) { }
}
How do I check if there are no non-protected elements in the array? The idea is that I can only operate on non-protected values, so I can pretend the array is empty if only protected values are present.
So far, my check is as follows:
{% if attributes is defined and attributes is not empty %}
<div{{ attributes }}>
{{ content }}
</div>
{% else %}
{{ content }}
{% endif %}
In its current form, this displays <div>[Content]</div>. Instead, I'd like to see: [Content]
Any help?

If this is in Drupal 8, you can pass the attributes value through render to find out, like this:
{% if attributes|render %}
<div{{ attributes }}>
{{ content }}
</div>
{% else %}
{{ content }}
{% endif %}

Extend twig
<?php
$twig = new Twig_Environment($loader);
$twig->addFilter(new Twig_SimpleFilter('accessible_properties', 'get_object_vars'));
Use it inside template
{% set public_attributes = attributes is defined ? (attributes|accessible_properties) : [] %}
{% if public_attributes is not empty %}
...
{% else %}
...
{% endif %}

Related

Printing out an array in twig using a for loop

i have to configurate a .csv file.
I have a variable that is either a single value or an array of values. If it is a single value, i want to put that single value into the cell, otherwise i want to put every value in the array into the cell.
This is my approach, but it's not iterating through the array. If the item is an array, it just puts nothing into to table cell. Do i need to increment i in some sort of way?
{% if item is iterable %}
{% for i in item[0..10]%}
*{{ item[i] }}
{% endfor %}
{% else %}
{{item}}
{% endif %}
Not sure why are you using {% for i in item[0..10]%} to iterate the item?
0..10 returns an array in twig, which will result in the following "code"
{% for i in item[Array] %}
This will return nothing as the index Array doesn't exist in the array item.
The proper way to iterate the value would be
{% if item is iterable %}
{% for i in item %}
{{ i }}
{% endfor %}
{% else %}
{{item}}
{% endif %}
If you are trying to display only 10 values from the array u'd go with
{% for i in item[0:10]%}
{{ i }}
{% endfor %}
or
{% for i in item|slice(0, 10) %}
{{ i }}
{% endfor %}

Twig accessing variables that need a variable expansion

I have the following code in a Twig template:
{% macro option_display(type) -%}
{% if server.options_array.options.{{type}}.name is defined %}
{{server.options_array.options.{{type}}.name}} +${{server.options_array.options.~type~.price}}
{%else%}
None
{% endif %}
{%- endmacro %}
I'm getting this error:
Twig_Error_Syntax: Expected name or number
How should I get it to expand the variable 'type' in that context? I've tried using ~type~ as well (concat).
would be something like $server['options_array']['options'][$type]['name']; in PHP.
Just use the bracket notation:
{% macro option_display(type) -%}
{% if server.options_array.options[type].name is defined %}
{{ server.options_array.options[type].name }} +${{ server.options_array.options[type].price }}
{% else %}
None
{% endif %}
{%- endmacro %}
You probably want to also check whether server.options_array.options[type] is defined before checking whether server.options_array.options[type].name is defined.
Furthermore, like the documentation of the macro tag says, "as with PHP functions, macros don't have access to the current template variables." So you probably need to pass the server variable to the macro as well.
So here's a more complete example:
{% macro option_display(server, type) -%}
{% set option = server.options_array.options[type]|default(null) %}
{% if option.name is defined %}
{{ option.name }} +${{ option.price }}
{% else %}
None
{% endif %}
{%- endmacro %}
{% from _self import option_display %}
{{ option_display(server, 'foo') }}
{{ option_display(server, 'bar') }}
Notice that I'm using a helper variable option and the default filter. Without the filter, you'd get a Twig_Error_Runtime exception if the server.options_array.options array doesn't have the key you are using. (Whether you get this exception or not depends on the value of the environment option strict_variables.)
See TwigFiddle

How to call function in twig in Symfony2?

In my model (Task) I have a function:
public function isTaskOverdue()
{
if ("now"|date('Y-m-d') > task.deadline|date('Y-m-d')){
return false;
} else{
return true;
}
}
In twig (edit) I want to display form:
{% extends 'base.html.twig' %}
{% block title %}app:Resources:Task:edit{% endblock %}
{% block body %}
{{ form(form) }}
{% endblock %}
I want to display form, if this function return true.
How can I call this function in twig?
Pass the task entity to twig and call method from object task :
{% if task.isTaskOverdue %}
{{ form(form) }}
{% endif %}
I think it should be your controller that receives the function result and display the form or not depending on it.
Also you can write your function like so :
public function isTaskOverdue()
{
return ("now"|date('Y-m-d') > task.deadline|date('Y-m-d'));
}
Pass the task entity to twig and do :
{% extends 'base.html.twig' %}
{% block title %}app:Resources:Task:edit{% endblock %}
{% block body %}
{% if "now"|date("Ymd") <= task.deadline|date("Ymd") %}
{{ form(form) }}
{% endif %}
{% endblock %}
But, caution :
If you just not display the form, there is a security issue, because if an attacker submit the form from an self rebuilded HTML page, your controller will receive the form data and apply it.
So I would do the check in the controller, and only create and pass the form to the twig template if the condition is true.
Then, in twig you can use :
{% if form is defined %}
{{ form(form) }}
{% endif %}

Is it possible to concatenate a variable to an if statement in Twig?

I am trying to concatenate a variable to an array key to get access to certain values in Twig, but no success so far.
I have a large PHP array that has for example keys like this:
$array = [
...
...
...
'test_1' => $test_1,
'test_2' => $test_2
];
I tried the following in my Twig template:
{% for i in 1..2 %}
{% if array.test_{{ i }} != 0 %}
<div>Test</div>
{% endif %}
{% endfor %}
but that doesn't work.
Is there a way to access values like this in Twig?
Try this:
{% for i in 1..2 %}
{% if array['test_' ~ i] != 0 %}
<div>Test</div>
{% endif %}
{% endfor %}

Use Twig variable as a property name of an other Twig variable

I must use a Twig variable as a property for another Twig variable.
In a for loop, I get the properties of a specific entity and want to use those properties to get the property-content for an entity variable in an other for loop.
Some code to make this clear:
{% for entity in entities %}
{{entity.foo}}, {{entity.bar}}<br />
{% for property in specialdynamicproperties %}
{{entity.property}} <!-- property has the content foobar for example, I want to use it as the property accessor for entity -->
{% endfor %}
{% endfor %}
Thanks.
The attribute function is what you are looking for.
Edit:
{{ attribute(object, method) }}
{{ attribute(object, method, arguments) }}
{{ attribute(array, item) }}
{% for object in objects %}
{% for column in columns %}
{{ attribute(object, column) }} {# equivalent to php $object[$column] #}
{% endfor %}
{% endfor %}
Using Twig Attribute Function (Twig > 1.2)

Categories