Twig Excel Bundle autosize - excel

How to set autosize in Twig Excel Bundle ?
https://twigexcelbundle.readthedocs.io/en/latest/

You can set the default autoSize property of a sheet to true via columnDimension:
{% xlssheet 'Worksheet' {
columnDimension: {
'default': {
autoSize: true
}
}
}%}
{# ... #}
{% endxlssheet %}
To define it for a specific column, use the letter of the desired column instead of default, per example the column D:
{% xlssheet 'Worksheet' {
columnDimension: {
'D': {
autoSize: true
}
}
}%}
{# ... #}
{% endxlssheet %}

Related

Variable Variable in Twig

I have the following variables in twig:( I can see them with kint)
data.po_user_setting.us_highlight_color1 = '#008080'
data.po_user_setting.us_highlight_color2 = '#00FFFF'
data.po_user_setting.us_highlight_color3 = '#FFFF00'
data.po_user_setting.us_highlight_color4 = '#FF0000'
data.po_user_setting.us_highlight_color5 = '#FF00FF'
and
verse.po_verse_highlight.hl_rating = Returns [1-5]
How can I show the dynamic variable like this? Neither of these lines work:
{{_context['data.po_user_setting.us_highlight_color' ~ verse.po_verse_highlight.hl_rating]}}
{{attribute(_context, 'data.po_user_setting.us_highlight_color' ~ verse.po_verse_highlight.hl_rating)}}
The problem you are facing is the variable you want to access is actually an array.
With your current code, twig is looking for a variable called e.g., data.po_user_setting.us_highlight_color.foo, translated to $_context['data.po_user_setting.us_highlight_color.foo']
To actually access the variable you want, you would need to treat the variable like an array:
{{ {{ _context['data']['po_user_setting']['us_highlight_color'~ verse.po_verse_highlight.hl_rating] }} }}
This is quite long to type every time, so to reduce the typing you could use a macro or extend twig
macro
{% macro get_array_value(context, key) %}
{% set value = null %}
{% for key in key|split('.') %}
{% set value = loop.first ? context[key]|default : value[key]|default %}
{% endfor %}
{{ value }}
{% endmacro %}
As macro's don't have access to the special variable _context you would to pass this every time when you want to call the macro, e.g.
{% import _self as macros %}
{{ macros.get_array_value(_context, 'data.po_user_setting.us_highlight_color' ~ verse.po_verse_highlight.hl_rating) }}
extending twig
<?php
$twig->addFunction(new \Twig\TwigFunction('get_array_value', function ($context, $variable) {
$keys = explode('.', $variable);
if (empty($keys)) return;
$value = $context[array_shift($keys)] ?? [];
foreach($keys as $key) {
$value = $value[$key] ?? [];
}
return !empty($value) ? $value : null;
}, ['needs_context' => true,]));
Then you can call this function like the following in twig
{{ get_array_value('data.po_user_setting.us_highlight_color' ~ verse.po_verse_highlight.hl_rating) }}

TWIG - include variables in different template

I would like to include the same variables in different templates
vars_catchphrase.twig
{% set catchphrase_size = '' %}
{% if var.tile_catchphrase|length <= 4 %}
{% set catchphrase_size = 'size-lg' %}
{% elseif var.tile_catchphrase|length >= 5 and var.tile_catchphrase|length <= 8 %}
{% set catchphrase_size = 'size-md' %}
{% elseif var.tile_catchphrase|length >= 9 and var.tile_catchphrase|length <= 12 %}
{% set catchphrase_size = 'size-sm' %}
{% elseif var.tile_catchphrase|length >= 13 %}
{% set catchphrase_size = 'size-xs' %}
{% endif %}
I tried to include with this (because the context is sometime different) :
{% include 'vars_catchphrase.twig' with { 'var' : post } %}
When the context is different from post I use another one :
{% include 'vars_catchphrase.twig' with { 'var' : item } %}
example.twig
{% for item in list %}
{% include 'vars_catchphrase.twig' with { 'var' : item } %}
<p class="catchphrase {{ catchphrase_size }}">{{ item.title }}</p>
{% endfor %}
The variable is empty. Can I have some help please ?
Templates you include have their own variable scope, this means variables defined inside this template will not be known out the template. This said, included templates also can't alter the parent's context (by default), this is due to twig passing the context array by value, not by reference.
foo.twig
{% set foo = 'foo' %}
{% include 'bar.twig' %}
{{ foo }}
bar.twig
{% set foo = 'bar' %}
The example above will still output foo
In order to solve your problem, I'd suggest adding a custom filter to twig
<?php
$twig->addFilter(new \Twig\TwigFilter('catchphrase_size', function($value) {
switch(true) {
case strlen($value->tile_catchphrase) >= 13: return 'size-xs';
case strlen($value->tile_catchphrase) >= 9: return 'size-sm';
case strlen($value->tile_catchphrase) >= 5: return 'size-md';
default: return 'size-lg';
}
});
This way you can use the filter where ever,
{% for item in list %}
<p class="catchphrase {{ item|catchphrase_size }}">{{ item.title }}</p>
{% endfor %}

Twig: how to add an object into multi level object

In twig template I have an object with multiple levels
I need to add a new object into the multiple object as the sub object
{%
set data = {
'first': 'First',
'data': {
'val_1': 'val_1'
}
}
%}
this should be added to data val_2: val_2
expected result:
{%
set data = {
'first': 'First',
'data': {
'val_1': 'val_1',
'val_2': 'val_2'
}
}
%}
First, in Twig terminology, that's not an object or a key-value array but a hash (see Twig's documentation of literals).
You can't add an item to a hash e.g. by doing {% set data.second = 'Second' %}. Instead you need to use the merge filter:
{%
set data = data|merge({
second: 'Second',
})
%}
{{ dump(data) }}
{# Prints this:
array(3) {
["first"]=>
string(5) "First"
["data"]=>
array(1) {
["val_1"]=>
string(5) "val_1"
}
["second"]=>
string(6) "Second"
}
#}
So, to add an item to a hash inside a hash, you need to use the merge filter twice:
{%
set data = data|merge({
data: data.data|merge({
val_2: 'val_2',
}),
})
%}
{# Prints this:
array(3) {
["first"]=>
string(5) "First"
["data"]=>
array(1) {
["val_1"]=>
string(5) "val_1"
["val_2"]=>
string(5) "val_2"
}
["second"]=>
string(6) "Second"
}
#}
If you do lots of this kind of variable manipulation in Twig, it might be a sign that some of that code might be better put in a controller or model or whatever.

Trouble passing a string from an array to a variable within a for loop

Im setting a "category" and passing it to a template that I'm including:
{% set categoryA = {
category: "categoryA",
}
%}
{% include "something.twig" with categoryA %}
{% set categoryB = {
category: "categoryB",
}
%}
{% include "something.twig" with categoryB %}
This is working fine but I'm repeating a lot of code which I want to avoid (in my actual code there are more than 2 categories).
Im trying to put the categories in an array and include something.twig for each one, passing a different category for each instance:
{% set categories = ['categoryA', 'categoryB', 'categoryC', 'categoryD', 'categoryE'] %}
{% for i in categories %}
<h3>{{ i }}</h3>
{% set categoryOption = {
category: {{ i }},
}
%}
{% include "something.twig" with categoryOption %}
{% endfor %}
The title in the h3 is printed OK however the categoryOption category is passed as [object Object] rather than the string name as I need
For example, you use category in the "something.twig":
...
{{ category|default }}
...
So you can use "include" like:
{% include "something.twig" with { category: 'Name of Category' } %}
Full code:
{% set categories = ['categoryA', 'categoryB', 'categoryC', 'categoryD', 'categoryE'] %}
{% for i in categories %}
<h3>{{ i }}</h3>
{% include "something.twig" with { category: i } %}
{% endfor %}

Check if variable is string or array in Twig

Is it possible to check if given variable is string in Twig ?
Expected solution:
messages.en.yml:
hello:
stranger: Hello stranger !
known: Hello %name% !
Twig template:
{% set title='hello.stranger' %}
{% set title=['hello.known',{'%name%' : 'hsz'}] %}
{% if title is string %}
{{ title|trans }}
{% else %}
{{ title[0]|trans(title[1]) }}
{% endif %}
Is it possible to do it this way ? Or maybe you have better solution ?
Can be done with the test iterable, added in twig1.7, as Wouter J stated in the comment :
{# evaluates to true if the users variable is iterable #}
{% if users is iterable %}
{% for user in users %}
Hello {{ user }}!
{% endfor %}
{% else %}
{# users is probably a string #}
Hello {{ users }}!
{% endif %}
Reference : iterable
Ok, I did it with:
{% if title[0] is not defined %}
{{ title|trans }}
{% else %}
{{ title[0]|trans(title[1]) }}
{% endif %}
Ugly, but works.
I found iterable to not be good enough since other objects can also be iterable, and are clearly different than an array.
Therefore adding a new Twig_SimpleTest to check if an item is_array is much more explicit. You can add this to your app configuration / after twig is bootstrapped.
$isArray= new Twig_SimpleTest('array', function ($value) {
return is_array($value);
});
$twig->addTest($isArray);
Usage becomes very clean:
{% if value is array %}
<!-- handle array -->
{% else %}
<!-- handle non-array -->
{% endif % }
There is no way to check it correctly using code from the box.
It's better to create custom TwigExtension and add custom check (or use code from OptionResolver).
So, as the result, for Twig 3, it will be smth like this
class CoreExtension extends AbstractExtension
{
public function getTests(): array
{
return [
new TwigTest('instanceof', [$this, 'instanceof']),
];
}
public function instanceof($value, string $type): bool
{
return ('null' === $type && null === $value)
|| (\function_exists($func = 'is_'.$type) && $func($value))
|| $value instanceof $type;
}
}
Assuming you know for a fact that a value is always either a string or an array:
{% if value is iterable and value is not string %}
...
{% else %}
...
{% endif %}
This worked good enough for me in a project I was working on. I realize you may need another solution.

Resources