I try to call a static helper method inside Twig (Timber).
{{ function('Theme\Helpers::get_template_name') }}
Warning: call_user_func_array() expects parameter 1 to be a valid
callback, class 'ThemeHelpers' not found in
/var/www/html/wp-content/plugins/timber-library/lib/Twig.php on line
268.
Does anyone know how to call a method of a different class inside Twig?
As far as I know you can't call PHP classes directly from your twig template.
What you can do is setting up a Twig filter which communicates with your class
and returns the needed value.
You would have this in your php controller file that is responsible to load your twig template:
<?php
function twg_get_template_name() {
# edit this according to the implementation of your class:
return Helpers::get_template_name();
}
function add_to_twig($twig) {
/* this is where you can add your own fuctions to twig */
$twig->addExtension(new Twig_Extension_StringLoader());
$twig->addFilter('twg_get_template_name', new Twig_Filter_Function('twg_get_template_name'));
return $twig;
}
add_filter('get_twig', 'add_to_twig');
In your Twig template you would call the filter like this:
{{ ''|twg_get_template_name }}
Because it's a filter function it expects a value "to filter", so pass at least an empty string.
If I were in that situation I probably would determine the name of the template in your
controller and send the value to your Twig template directly instead of calling the php class
via a filter-function.
You can call static functions from a Twig file in Timber using the array notation, where first item is the name of the class and the second item the name of the static method you want to call:
{{ function( [ 'Theme\Helpers', 'get_template_name' ] ) }}
Thanks for your answer.
I tried your approach - it works. But using a filter feels a little hacky, especially when no value is passed. Why not create a timber function the same way as a filter?
Bridging own functions from plain php into twig is not great, but I also don't see another solution to this.
After playing around a little, I came up with a different approach. I now fixed my need by customizing the Timber Object and adding a template property to the post variable.
Looks something like this:
class OnepagePost extends TimberPost {
var $_template;
// Add template property to Twig Object
public function template() {
return Helpers::get_template_name( $this->custom['_wp_page_template'] );
}
}
Then inside the .php file where the Twig View gets called, I called the custom object like this:
$context['posts'] = new Timber\PostQuery( $args, 'OnepagePost' );
Timber::render('onepager.twig', $context);
Inside the Twig Template I'm able to get my custom property very easy (in my way the template):
{% for post in posts %}
{% include ["section/section-#{post.template}.twig"] %}
{% endfor %}
Related
I succssefully get data in store-front from entity by the following code.
public function addCustomfield(FooterPageletLoadedEvent $event): void
{
$customfieldResponse = $this->customfieldRoute->load(new Criteria(), $event->getSalesChannelContext());
$event->getPagelet()->addExtension('custom_field', $customfieldResponse->getcustomfield());
}
according to above code my custom data add in footer pagelet by api call successfully.
I wnat to get data of my plugin-config data in footer pagelet.
If you have any suggestion then tell me!
You can access the plugin config directly over twig inside the template:
{% set myConfig = config('MyPluginName.config.myConfigValue') %}
I have been following https://developer.shopware.com/docs/guides/plugins/plugins/storefront/add-custom-javascript to create a javascript plugin. But, I am struggling with adding options through twig template. I have something like the following:
Twig file : product.html.twig:
{% set contentModalOptions = {
cmsContentId: "some-hash",
navigationUrl: path('frontend.cms.page'),
failSafeRedirectUrl: '/some-failsafe-url/'
} %}
<div>
<a target="_self" href="#" data-content-modal="true" data-content-modal-options="{{ contentModalOptions|json_encode|escape('html_attr') }}">
help text
</a>
</div>
plugin file : custom-plugin.js:
import Plugin from 'src/plugin-system/plugin.class';
export default class ContentModalPlugin extends Plugin {
static options = {
cmsContentId: '',
navigationUrl: '',
failSafeRedirectUrl: ''
};
init() {
console.log(this);
console.log(this.options); // empty values
}
}
Notes:
In the browser, I see that values set using twig as the HTML attribute.
Plugin has been registered and works with the template.
console.log() in the plugin doesn't print any values that are set from twig. It just shows the options object that has been initialized in the plugin.
Any help is appreciated.
I assume you register the plugin like this:
PluginManager.register('ContentModal', ContentModalPlugin, '[data-content-modal]');
Within the constructor of the Plugin class this.options = this._mergeOptions(options); should then called, which in turn parses the data-${dashedPluginName}-options attribute. It should throw an error if it can't parse the json:
`The data attribute "data-${dashedPluginName}-options" could not be parsed to json: ${e.message}`
Are the any errors when you look at the console of your browsers dev tools?
For further debugging you could also try calling super._mergeOptions(this.options); from your init method.
Now, I see what the problem was. When I registered my plugin, I had the following:
PluginManager.register('ContentModalPlugin', ContentModalPlugin, '[data-content-modal]');
So, I tried passing the options with data-content-modal-options attribute through twig but it seems that the resolved plugin name in _mergeOptions() at src/plugin-system/plugin.class takes the plugin name (i.e the string that is the first argument of the register function) and not the attribute definition in the register method.
So, adding a html attribute as data-content-modal-plugin-options based on my class name resolved the problem.
I defined my route so:
$app->get('/about', function ($request, $response, $args) {
return $this->view->render($response, 'about.twig');
})->setName('about.page');
I'm interested to get route link by name like: {% get_route('about.page') %}
How can I achieve this?
In Slim3 there is the path_for(name) function. F.ex:
{{ path_for('about.page') }}
Reference: http://www.slimframework.com/docs/features/templates.html
The slim/twig-view component exposes a custom path_for() function to your Twig templates. You can use this function to generate complete URLs to any named route in your Slim application. The path_for() function accepts two arguments:
1 A route name
2 A hash of route placeholder names and replacement values
Note: The path_for uses the function of the router which is $router->pathFor(..)
Why not to use {%
{% is a control structur in twig, Message: Unknown "path_for" tag in "base.twig" at line XX. is displayed because there is no such tag as control structur defined so twig doesn't know that this is actually a function.
So use the output structur in twig {{.
Is this possible?
Yes.
IIRC
{{ path_for('about.page') }}
Reference:
https://github.com/slimphp/Twig-View/blob/master/src/TwigExtension.php#L37
There is some security reasons and I want to prevent access to class constants in twig. How can I do it?
Note: It is possible to access constants with code below.
{{ constant('Entity\\Demo::MY_CONSTANT') }}
sandbox is not the cure. Because in the system the user writes his own template, this brings security issues.
For that reason function overriding in extension may be a good solution.
$environment = new Twig_Environment($loader, array('autoescape' => self::$_autoEscapeOpened));
$myTwigExtension = new MyTwigExtension();
//note that MyTwigExtension extends Twig_Extension
$environment->addExtension($myTwigExtension);
//here is MyTwigExtension
class MyTwigExtension extends \Twig_Extension {
//in my twig extension, there is a method called getFunctions. If not, write one.
public function getFunctions() {
$functions = array(
new \Twig_SimpleFunction('constant', array($this, 'constant')),
);
return $functions;
}
//and add the customized constant function in your extension here!
public function constant($variable){
return '';
}
}
if you don't want to use extension, see http://twig.sensiolabs.org/doc/advanced.html#functions
Ant the result is nice, there is no output in the screen, without any sandbox use. (solution is on backend)
Hope this helps.
I believe you can do this with the Sandbox extension:
http://twig.sensiolabs.org/doc/api.html#sandbox-extension
This extension allows you to define a security policy which basically has a whitelist of functions, tags, filters...
You can enable sandbox mode globally, or just use sandbox mode for a specific include (default behavior):
{% sandbox %}
{% include 'user.html' %}
{% endsandbox %}
I'm trying to customize a specific widget, like in the documentation : http://symfony.com/doc/current/cookbook/form/form_customization.html#how-to-customize-an-individual-field
The problem is that in this custom block, I need to use a variable from my actual template. I thought "blocks have access to variables from outer scopes", but apparently not in this case :
{% extends "CDASvBundle::layout.html.twig" %}
{% block _contact_activity1_widget %}
<select name="contact[activity1]">
{% for key, child_contact_categories in contact_categories_tab %}
<option value="{{key}}">{{child_contact_categories}}</option>
{% endfor %}
</select>
It's saying that contact_categories_tab is undefined, but outside of this block (in the normal content block for example), it works !
I tried something like :
{% use 'form_div_layout.html.twig' with contact_categories_tab as contact_categories_tab %}
But that doesn't either.. Though I'm not sure I understand if I have to use use and how !
I see one other solution that I haven't tried yet : put this customization in another template. But I don't really want to do that (few lines in a new template), there should be a way to do that in only ONE template ?!
Finally found the answer in a previous post :
Each symfony form type extents AbstractType class.
AbstactType class has method:
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->set('img_src', '120x100.jpg');
$view->set('my_variable', $foo);
}
You can create this method on your form type and next in your twig:
{{ asset(img_src) }}
Source : How to get entity or pass variable to Symfony2 twig form widget?