Twig - Including templates from templates with no context - twig

I inherited an app that uses Symfony2 with Twig which is a new thing for me, so please feel free to point out the obvious that I'm missing.
Ran into an issue where the same template being included from two different other templates was unable to include a third template depending on which of the two "calling" templates was including it.
In other words,
Two main view templates:
smallpictures.html.twig
bigpictures.html.twig
both include a third template:
picturegrid.html.twig
in picturegrid template, there is another include for the template:
importantstuff.html.twig
importantstuff template would not properly be loaded depending on whether you were viewing smallpictures.html.twig or bigpictures.html.twig
The include statement in smallpictures was like so:
{{ include('MyBundle:SmallPictures:picturegrid.html.twig') }}
The include statement in bigpictures was like so:
{% include 'MyBundle:SmallPictures:picturegrid.html.twig' with {'param1': param1, 'param2': 'param2'} only %}
The include statement in picturegrid for importantstuff was like so:
{% include 'partials/components/stuff/importantstuff.html.twig' %}
This last included did not work correctly when used from bigpictures template - it loaded up blank content on the site.
I don't think the difference in the syntax for the include statement is important here, but according to the Twig documentation the keyword only removes access to the context for the included template. When I remove this keyword, the importantstuff template gets included correctly.
Question - if the template does not have context, how should other templates be included from it? The folder structure looks like this:
app
-- Resources
---- MyBundle
------ views
-------- SmallPictures
-------- BigPictures
---- views
------- partials
--------- components
------------ stuff

Related

Which twig template to extend for a custom theme?

I apologise before for a long explanation - I have a hard time explaining it to myself.
I run Shopware 6 locally and using the development template. I needed to remove the product number from the product detail page. So, I override the twig template "buy-widget.html.twig":
{% sw_extends '#Storefront/storefront/page/product-detail/buy-widget.html.twig' %}
{% block page_product_detail_ordernumber_container %}
{% endblock %}
Works as expected - if I have not change the layout template for the product, but using the Shopware default.
But, when I change the layout to a custom layout (the only difference is that the image thumbs is bellow the main image) the product number is back?!
Checking with the Symfony Profiler, I can see that it's now another twig template (from a folder "component/.." responsible for displaying the product number.
Question: Am I correct to assume that I should extend the twig template from this component folder if I'm using a custom layout? I have not find anything in the docs about these "small" details. And if one need to be sure that a custom theme works in every case, you must make the changes (using sw_extends) in two files?
/ Magnus

Flask | JINJA 2: render_template_string() with macro imported in context

I am looking to make macros available inside of the articles for my flask blog. When the body of my blog changes I run the following code to render the body into HTML:
target.body_html = bleach.linkify(bleach.clean(render_template_string(value),tags=allowed_tags, attributes=allowed_attr, strip=True))
render_template_string(value) is the part I'm concerned about. To use a macro inside of the template string (value), every single string has to include the following in order for me to use the macros from this file in the article body:
{% import "includes/macros.html.j2" as macros %}
This would not be reasonable to ensure that writers have access to the macros that I write in all of their articles. Is there any way to pass that argument via the render_template_string() function so that it doesn't have to be defined in every string? Or to otherwise create a template that the string is rendered inside of? Something like the following:
render_template_string(string,macros=function_to_import_macros("includes/macros.html.j2"))
While there does not appear to be a solution to pass an entire macros template as context, get_template_attribute does appear to allow you to pass individual macros one at a time. Example:
includes/macros.html.j2:
{% macro hello() %}Hello!{% endmacro %}
{% macro hello_with_name(name) %}Hello, {{ name }}!{% endmacro %}
Template rendering code:
hello = get_template_attribute("includes/macros.html.j2","hello")
hello_with_name = get_template_attribute("includes/macros.html.j2","hello_with_name")
return render_template("index.html", hello=hello,hello_with_name=hello_with_name)
index.html:
{{ hello() }}
{{ hello_with_name("Bob") }}
This solution will allow for adding individual macros to the context while rendering a template or template_string and can even be added to the global context via this method. If anyone knows how to add an entire template full of macros, that'd rock, but this allows the basic needed functionality.

Grav CMS: how to show/hide parts of the page depending on conditions?

The Grav's documentation clearly describes how a whole page or a folder could be hidden from unregistered users. It also describes how a whole page could be seen only by particular user groups.
But what about pieces of a page, let's say, some links or a private info I want to show on some conditions?
Ok, for registered users I found a snippet at Login plugin docs:
{% if grav.user.authenticated %}
content for registered users goes here
{% endif %}
But going wider - how can I show/hide pieces of a particular page depending on some custom logic in PHP code, i.e. not necessarily user related?
I'm thinking about a twig/shortcode plugin, something like:
{% if some.custom.condition.or.PHP.function %}
hidden content goes here
{% endif %}
or
[hidden_if_something] hidden content goes here [/hidden_if_something]
But not sure how exactly this should be implemented. So working examples would be appreciated. Thanks.
There is a recipe in the Grav documentation here. This provides an example of how to render the output of a PHP code result in a twig template.
In the example they create a plugin, and implement a twig extension providing access to a php function. They can then simply call that php function like in a twig template.
{{ example() }}
Following that example, you can implement whatever logic you would like in php, and call the function in a twig if statement.
{% if example() == true %}
your conditional output
{% endif %

Symfony Server crashes when extending FOSUserBundle's default template layout.html.twig

I am trying to get the basic user login running from the FOSUserBundle.
I am using Symfony 3.0.6.
I followed the description to setup everything from the FOSUserBundle:
https://symfony.com/doc/master/bundles/FOSUserBundle/index.html
DB is up and running everything seems fine except I cant figure out how to override the layout.html.twig from the FOSUserBundle.
I followed this description for achieving that:
https://symfony.com/doc/master/bundles/FOSUserBundle/overriding_templates.html
I now have a file "layout.html.twig" in the folder "Resources/FOSUserBundle/views" with the content being the same as in the last link provided above.
This leads to the following error:
Unable to find template "layout.html.twig" (looked into:
[somePathInfo]) in FOSUserBundle::layout.html.twig at line 1.
Now I changed the first line in the "layout.html.twig" Template to be
{% extends 'FOSUserBundle::layout.html.twig' %}
And this then leads to the symfony server to crash stating
>php bin/console server:run -v
[OK] Server running on http://127.0.0.1:8000
// Quit the server with CONTROL-C.
RUN "C:\xampp\php\php.exe" "-S" "127.0.0.1:8000" "[PATH]\myProject\vendor\symfony\symfony\src\Symfony\Bundle\FrameworkBundle\Resources\config\router_dev.php"
RES -1073741571 Command did not run successfully
[ERROR] Built-in server terminated unexpectedly.
I am stuck here...
Any ideas are very welcome.
EDIT: The FOSUserBundle installed by the composer (which I use through the current PHP-Storm plugin) is installed at the path:
[projectPath]\vendor\friendsofsymfony\user-bundle\Resources\views\layout.html.twig
In the docu however allways "FOSUserBundle" only is mentioned and I don't know how to figure out if that mapping fits to the path in my project.
Any hints for this issue are very wellcome as well.
When you override standart FOSUser layout you need to place your layout into app/Resources/FOSUserBundle/views/layout.html.twig. great, you did this. it's just a layout, it should not extend standart FOSUser layout, so remove line {% extends 'FOSUserBundle::layout.html.twig' %}. But usually developers make one base layout, in my case it is \app\Resources\views\base.html.twig, so if I want to override fosuser layout I will have in app/Resources/FOSUserBundle/views/layout.html.twig something like this
{% extends 'base.html.twig' %}
{% block title %}User Management{% endblock %}
{% block content %}
{% block fos_user_content %}{% endblock %}
{% endblock %}
In first line you extend your base layout not FOSUser. You may not extend something, maybe you have separate complete layout for this template.
The crash does make sense.
When you write:
{% extends 'FOSUserBundle::layout.html.twig' %}
The Symfony will first try to load app/Resources/FOSUserBundle/views/layout.html.twig. Failing to find the file will revert to similar path but inside the vendor directory. And if you are trying to extend FOS's template from within your FOS overriden template, that would create recursive loop:
app/Resource/FOSUserBundle/views/layout.html.twig
^^ extends
app/Resource/FOSUserBundle/views/layout.html.twig
^^ extends
app/Resource/FOSUserBundle/views/layout.html.twig
....
and so on...
So, this is not a way to solve the problem.
Make sure that your template is well placed in your app directory and not your bundle, as Denis Alimov suggested in a comment.

Passing string variables through include in twig and slim framework

I am using Slim Framework and Twig.
I want to apply the DRY by using partials. I have a form that is reused in several views with different variables such as titles and route (url) names.
I am struggling on how to make it work on url names.
For example, there is this link using the ´urlFor´ helper with parameter as follows inside a view:
The link
So that is the link I want to pass to the partial template since, it is different in each view, I want to use the partial form. I have tried several approaches but it does not work. I don't know how to pass this string containing ' inside.
For example, I have tried this partial call inside the parent view like this:
{% include 'partials/partial.php' with {'theUrl': "urlFor('route.name', {parameter: value})"} %}
And inside the partial like this:
Show more
It does not work because in the browser's url I see the following:
http://myproject.dev/pages/urlFor('route.name',%20%7Bparameter:%201%7D)
It looks like it is not being escaped properly. Any ideas how to fix this when passing route names with urlFor()?
Without the greatest possibility for testing i think i found the problem. You are simply adding the function inside a string and that does not give the parser an oportunity to resolve the method, because it's basicly just a string.
{% include 'partials/partial.php' with {'theUrl': "urlFor('route.name',{parameter: value})"} %}
Should be
{% include 'partials/partial.php' with {'theUrl': urlFor('route.name',{parameter: value})} %}

Resources