Assetic image filter and localized resources - symfony

For one of our projects we have a couple of headers which are different for each locale. At this moment I'm using the assetic image function to load the correct image, like this:
{% image '#AgendaBundle/Resources/public/images/header_1.png' output='/images/header_1.png' %}
<img src="{{ asset_url }}" class="mod-rounded" />
{% endimage %}
To add a translated version of the headers, the only way to do this seems to be hardcoding the locale:
{% if app.request.locale == 'nl' %}
{% image '#AgendaBundle/Resources/public/images/header_1.png' output='/images/header_1.png' %}
<img src="{{ asset_url }}" class="mod-rounded" />
{% endimage %}
{% else %}
{% image '#AgendaBundle/Resources/public/images/header_1_en.png' output='/images/header_1_en.png' %}
<img src="{{ asset_url }}" class="mod-rounded" />
{% endimage %}
{% endif %}
This seems tedious, error prone and hard to maintain. Is there a better and more elegant solution available?

Related

Slice Twig path

I would like to delete the first occurrence of '/' in my twig path. I need it to show image in my pdf. I don't know how to deal with it and need help from someone smarter.
<p>{% path(project.mainImage), 'reference' %}</p>
Gives me:
/upload/media/img/a6ab300301dd8e5de89bac068a16aaa9e90b2a1b.jpeg
I need:
upload/media/img/a6ab300301dd8e5de89bac068a16aaa9e90b2a1b.jpeg
Ok guys, I am just stupid.
Here is the answer:
{% set rendered %}{% path project.mainImage, 'reference' %}{% endset %}
<img src="{{ rendered|replace({'/upload':'upload'}) }}">
Works like a charm.
You could use the slice Twig filter, like this:
{% set rendered %}{% path project.mainImage, 'reference' %}{% endset %}
<img src="{{ rendered|slice(1) }}">
UPDATE:
And if you only want to do it on routes starting with /, you could do like this:
{% set rendered %}{% path project.mainImage, 'reference' %}{% endset %}
{% if rendered|slice(1) == '/' %}
<img src="{{ rendered|slice(1) }}">
{% else %}
<img src="{{ rendered }}">
{% endif %}

Assigning output of a twig function to a twig variable

I have the twig/assetic code below:
{% if post.media %}
{% image '#ApplicationMyBundle/Resources/images/AjaxLoader-298x179.gif' output='/images/AjaxLoader-298x179.gif' %}
<img src="{{ asset_url }}" data-src="{% path post.media, 'news_size_4' %}" />
{% endimage %}
{% endif %}
The real image path is in {% path post.media, 'news_size_4' %}, I need to get this output in to a variable so i can use it elsewhere. {{ asset_url }} is no good as that only gives me the ajaxloader image.
Is there anyway this can be done?
As suggested by Hakim in a comment, you can use the set Twig tag.
Define the variable:
{% set myPath %}
{% path post.media, 'news_size_4' %}
{% endset %}
Display this variable:
{{ myPath }}

Is it possible to do some sort of implicit loop with Twigs `{% image %}` to return all images in the directory?

Considering that Twig has it's {% for %} loops and it's {% image %} sections, is there something such as the following be done with Twig to return all images within the AppBundle/Resources/images/gallery/ directory? It would seem to make sense but I've not been able to find anything so far:
{% image #AppBundle/Resources/images/gallery/*.jpg %}
<img src="{{ asset_url }} />
{% endimage %}
Yes, that is possible. Assetic just doesn't distinguish between different file types:
{% image '#AppBundle/Resources/images/gallery/*' %}
<img src="{{ asset_url }}" />
{% endimage %}
This will render all images from the gallery directory, no matter the file extension.
The same can be done with CSS and JS files via
{% stylesheets '#AppBundle/Resources/css/*' %}
<img src="{{ asset_url }}" />
{% endstylesheets %}
{% javascripts '#AppBundle/Resources/js/*' %}
<img src="{{ asset_url }}" />
{% endjavascripts %}

How to use variables in Assetic

I searched a lot but could not find a solution to achieve this:
{% for i in 1..6 %}
<li>
{% image '#MyBundle/Resources/public/images/college/demo/facilities/thumbs/laboratory/'~i~'.jpg' %}
<img class="facThumb" src="{{ asset_url }}" alt="Facilitiy"/>
{% endimage %}
</li>
{% endfor %}
Name of the images should be dynamic. Please help.
The above code throws error:
Unexpected token "operator" of value "~"
Solution:
According to what #Nic posted (accepted answer), the only workaround seems to be this:
{% for i in 1..6 %}
<li>
<img src="{{ asset('bundles/digicreekil/images/college/demo/facilities/thumbs/laboratory/t'~i~'.jpg') }}" alt='demo'/>
</li>
{% endfor %}
You can't use variables in Assetic (and therefore in the {% image %} tag).
The reason is, according to Kris Wallsmith (creator of Assetic):
(...) that Assetic needs to be able to parse a Twig template and extract any assets that are defined there. This is not possible if you use a variable in the tag.
Christophe Coevoet adds:
The assets are dumped when using the CLI command for this, not when rendering the page. So you cannot use variables as you don't have their values.
See this GitHub issue for the complete conversation.
Remember that Assetic creates and optimizes the assets when you run app/console assetic:dump, not when the page is actually rendered. Therefore, it cannot know of any values, it can only work with static assets.
So if you want to work with dynamic assets, you'll have to do something like this:
{% for i in 1..6 %}
<li>
<img class="facThumb" src="{{ asset('images/college/demo/facilities/thumbs/laboratory/'~i~'.jpg') }}" alt="Facilitiy"/>
</li>
{% endfor %}
In this case, you can iterate through the numbers 1-6 and use the variable in the asset's URL because you're not using Assetic, but Twig's asset() function. asset() simply returns the full URL of the asset, it doesn't do any optimizations so it can be executed during runtime.
But if you want to use Assetic's optimizations and filters, you can also give it the static assets:
<li>
{% image '#MyBundle/Resources/public/images/college/demo/facilities/thumbs/laboratory/1.jpg' %}
<img class="facThumb" src="{{ asset_url }}" alt="Facilitiy"/>
{% endimage %}
</li>
<li>
{% image '#MyBundle/Resources/public/images/college/demo/facilities/thumbs/laboratory/2.jpg' %}
<img class="facThumb" src="{{ asset_url }}" alt="Facilitiy"/>
{% endimage %}
</li>
<li>
{% image '#MyBundle/Resources/public/images/college/demo/facilities/thumbs/laboratory/3.jpg' %}
<img class="facThumb" src="{{ asset_url }}" alt="Facilitiy"/>
{% endimage %}
</li>
(etc.)
This way, you'll have to copy the same code 6 times, but it allows you to use Assetic.

Adding JS and CSS cleanly from included Twig templates

I'm looking to find out if there's a clean way to add JS and CSS from included templates.
So, for example, if layout.html.twig has:
{% include 'GenericBundle:Generic:page.html.twig' with {'data': data} %}
...
{% block javascript %}
{% javascripts
'#GenericBundle/Resources/public/js/app/jquery/jquery.min.js'
'#GenericBundle/Resources/public/js/lib/bootstrap/bootstrap.min.js'
%}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
{% endblock %}
And in the generic bundle page I'd like to include some more Javascript but add it to the established Javascript block to keep to HTML and JS best practices.
Is there a clean way to do this? I'm using Symfony2, and could probably cludge together a solution using Singletons and such, but I'd rather a cleaner method if there's one available.
I know I'm a little late to the party, but with Twig 1.2, you can utilize the use tag and the block function:
GenericBundle:Generic:page.html.twig
{% block javascripts %}
<script src="..."></script>
{% endblock %}
{% block included_content %}
Bar
{% endblock %}
layout.html.twig
{% use 'GenericBundle:Generic:page.html.twig' with javascripts as page_javascripts %}
{% block javascript %}
{% javascripts
'#GenericBundle/Resources/public/js/app/jquery/jquery.min.js'
'#GenericBundle/Resources/public/js/lib/bootstrap/bootstrap.min.js'
%}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
{{ block('page_javascript') }} // Don't forget the 'braces'
{% endblock %}
...
{{ block('included_content') }} // Don't forget the 'braces'

Resources