Using a PHP function in Twig - php

I have a PHP code to add a new class for my Twig template in my common controller in: "opencart\htdocs\catalog\controller\common\cart.php"
The code should check if the Device is Mobile or not.
function onStart()
{
// Anonymous Class only working on PHP7
$this['code'] = new class {
public function MobileDetect() {
return preg_match("/(android|avantgo|blackberry|bolt|boost|cricket|docomo
|fone|hiptop|mini|mobi|palm|phone|pie|tablet|up\.browser|up\.link|webos|wos)/i"
, $_SERVER["HTTP_USER_AGENT"]);
}
};
}
But now I don´t know how to address that function correctly from my twig side at:
opencart\htdocs\catalog\view\theme\default\template\common\cart.twig
I tried something like this, but it didn´t seem to work:
{% if code.MobileDetect() is defined %}
If a device is mobile I want to use a completely different HTML construct.

What you need to do is create your own Twig function:
https://twig.symfony.com/doc/3.x/advanced.html#functions
So using their examples you should be able to do something like
$function = new \Twig\TwigFunction('MobileDetect', function () {
return preg_match("/(android|avantgo|blackberry|bolt|boost|cricket|docomo
|fone|hiptop|mini|mobi|palm|phone|pie|tablet|up\.browser|up\.link|webos|wos)/i"
, $_SERVER["HTTP_USER_AGENT"]);
});
$twig->addFunction($filter);
Then call it like
{% if MobileDetect() %}

Related

EasyAdmin3 / Symfony / Twig - url generator with route name and params in Twig template

I'm trying to generate EasyAdmin3 url inside my template with some params, but for some reason they are not present in a controller.
Twig template:
xxx
yyy
Error with missing EA context:
zzz
Controller:
/**
* #Route("/admin/something/{id}", name="rounte_name")
*/
public function xyz($id = null, Request $request, AdminContext $context)
{
dd($_GET['id'], $request->request->all(), $context->getRequest()->request->all());
...
}
The $_GET['id'] works, but request and context are empty [].
Any idea how to generate route by name with params?
Thanks
I don't think you need the ea_url() helper function if you are just generating regular named routes in twig. You should be able to use the path() twig extension provided by Symfony.
{{ path(route_name, route_parameters = [], relative = false) }}
If you are trying to create a link to an EasyAdmin controller action, then you can use the ea_url() helper, but you have to specify the controller and action as well. Try something like:
{% set url = ea_url()
.setController('App\\Controller\\Admin\\FoobarCrudController')
.setAction('customFooAction')
.setEntityId(entity.instance.id)
.set('myParam', 'baz') %}
Custom Foobar Action
Then in your controller, everything should be available as per usual via the $context variable...
public function customFooAction(AdminContext $context)
{
$entity = $context->getEntity()->getInstance();
$myParam = $context->getRequest()->get('myParam');
}
This works for me, I hope it helps. 🙂

Rendered view is not displaying in my back office in PS 1.7

I am trying to create a view in the back office tab that I created in the installation of my Module. My Module adds the tab like this:
protected function _installTabs()
{
if(!$tabId = \Tab::getIdFromClassName('IezonPortfolio')) {
$tab = new \Tab();
$tab->class_name = 'IezonPortfolio';
$tab->module = $this->name;
$tab->id_parent = \Tab::getIdFromClassName('ShopParameters');
$tab->active = 1;
foreach (Language::getLanguages(false) as $lang):
$tab->name[(int) $lang['id_lang']] = 'My Portfolio';
endforeach;
return $tab->save();
}
new \Tab((int) $tabId);
return true;
}
This works fine and I can navigate to my Shop Parameters and click the My Portfolio tab. The issue I'm having is that it is blank. My ModuleAdminController looks like this:
class IezonPortfolioController extends ModuleAdminController {
private $_module;
public function __construct()
{
$this->bootstrap = true;
parent::__construct();
$this->_module = \Module::getInstanceByName('iezonportfolio');
}
public function indexAction()
{
return $this->render('#Modules/iezonportfolio/views/templates/admin/display.html.twig', array(
'contents_iezonportfolio' => $this->_module->selectAll()
));
}
}
My display.html.twig just has test in it to see if it would output anything which it didn't. On looking at the Docs it doesn't mention anything other than using the render function and returning it. Any help would be appreciated. I just get a blank Tab.
EDIT: After looking at some of the pre-installed modules and referencing them to the Docs, I saw that I was missing my route configuration. My Controller is in the documented directory set-up: iezonportfolio/controllers/admin/iezonportfolio.php so I made my route like this:
iezonportfolio:
path: iezonportfolio
methods: [GET]
defaults:
_controller: 'IezonPortfolio\Controllers\Admin\Controller::indexAction'
_legacy_controller: 'IezonPortfolioController'
_legacy_link: 'IezonPortfolioController:index'
This has still not yet fixed the blank display so I tried to dig deeper into some other modules and have now updated my display.html.twig to show this:
{% extends '#PrestaShop/Admin/layout.html.twig' %}
{% block content %}
Test
{% endblock %}
This did not fix the blank display either. I hope this addition is useful for future viewers.
This is not how the modern controllers works, you are extending legacy ModuleAdminController, take a look here:
https://github.com/PrestaShop/example-modules
you have a plenty of module examples, here's a little snippet from one of those modules:
declare(strict_types=1);
namespace PrestaShop\Module\DemoControllerTabs\Controller\Admin;
use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;
use Symfony\Component\HttpFoundation\Response;
class MinimalistController extends FrameworkBundleAdminController
{
/**
* #return Response
*/
public function indexAction()
{
return $this->render('#Modules/democontrollertabs/views/templates/admin/minimalist.html.twig');
}
}
I recommend you to think wether you want to use, or not, modern controller. It depends on wether you want to sell your module, use it in client projects etc.

Octobercms. How to prepare variable to component template?

Page code:
{% partial 'content/main' %}
Partial:
[services]
{% component 'services' %}
Component:
public function prepareVars()
{
$this->page['servicesList'] = $this->getProperty(); // function returns 123
}
Component template:
{{ servicesList }} //does not display anything =(
Why is not the variable being passed?
Hmm seems something odd, not sure about your onRun method in component
prepareVars will not call automatically we need to call it manually.
did you add prepareVars inside onRun as when page life-cycle called , onRun is called automatically so we need to add prepareVars there as well, so its code get executed.
public function onRun()
{
$this->prepareVars();
}
public function prepareVars()
{
$this->page['servicesList'] = $this->getProperty(); // function returns 123
}
if you are already doing this then please notify it in comment so we can look further.

Silex: translation not working in Twig

Currently, I develop a website by using the PHP micro-framework Silex. Now I try to use "TranslationServiceProvider" to translate my website into different languages. To achieve this, I have set the "locale" parameter :
$app->register(new Silex\Provider\TranslationServiceProvider(), array(
'locale' => 'pt'
));
Then, in my controller, I call the function "setLocale", like this:
$app['translator']->setLocale('it');
Now, if I display, always in my controller, the result of the translation its works fine:
$app['translator']->trans("hello"); // return "Buongiorno"
$app['translator']->getLocale(); // return "it"
But, if I call the same function in my template Twig, translation does not work:
{{ app.translator.trans('hello') }} // return: "Olá"
{{ app.request.locale }} // return: "pt"
So, I don't understand: translation works fine in my controller but when I want access translations in Twig, nothing happens.
Do you have any idea about what's going on?
Finally, I've found a solution to resolve my problem. In my "app.php" file, I have added the following code :
$app->before(function () use ($app) {
if ($locale = $app['request']->get('lang') or $locale = $app['request']->getSession()->get('_locale')) {
$app['locale'] = $locale;
$app['request']->setLocale($locale);
}
});
Then, I've written a function in my controller to change language:
public function changeLanguageAction(Request $request, Application $app, $language)
{
$app['request']->getSession()->set('_locale', $language);
return $app->redirect($app["url_generator"]->generate('index'));
}
Now, when I call "changeLanguage" function, all the translations work fine.
I don't know if this solution is a good practice but it works...

Using Twig to generate JSON

I want to have a URL that returns a simple JSON object. I am trying to use Twig to generate the JSON object:
{
"urls": [
{% for child in page.root %}
"{{ child.url }}"{% if not loop.last %},{% endif %}
{% endfor %}
]
}
The carriage returns will not remain in place though, and I keep getting a result that looks like this:
{'urls':['../ants/','../brick-report/','../the-pollution-intervention/','../barclay/','../broken-advertising/','../aldat-n-densom/','../thisisart/','../there-she-goes-again/']}
which Jquery will not parse with it's ajax or getJSON methods. It's totally ignoring this JSON. How might I convince Twig to put the right whitespace in place? I've looked at the manual and it only seems concerned with NOT inserting whitespace.
This works for me (twig template):
var parsedJSON = JSON.parse('{{ ['one', 'two', 'three']|json_encode|e('js') }}');
And this:
console.log(parsedJSON);
outputs:
Array ["one", "two", "three"]
in browser's console.
Twig has a filter for this.
json_encode, it uses PHP json_encode function.
for your case:
{{ {'urls': page.root}|json_encode }}
will output
{"urls":["..\/ants\/","..\/brick-report\/","..\/the-pollution-intervention\/","..\/barclay\/","..\/broken-advertising\/","..\/aldat-n-densom\/","..\/thisisart\/","..\/there-she-goes-again\/"]}
the code is tested and works. For more information take a look at the Twig Documentation for json_encode.
Generally it would make more sense to make controller return json directly, by returning JsonRespnse object
But if you really need to output JSON in Twig and assign it to variable, you can also use:
let foo = {{ bar|json_encode|raw }}
Don't use Twig to generate your json response.
In your controller, use:
return new Response(json_encode($var));
Sample:
public function sampleAction()
{
$urls = array('../test', '../something', '../sample');
return new Response(json_encode($var));
}
If URLs are generated from Symfony2 routes, you can use:
public function sampleAction()
{
$urls = array(
$this->generateUrl('my_test'),
$this->generateUrl('my_something'),
$this->generateUrl('my_sample'),
);
return new Response(json_encode($var));
}
Try wrapping your template in an autoescape block:
{% autoescape 'js' %}
{ "href": "{{ my_url }}" }
{% endautoescape%}
Thats easy if you extend twig.
First, create a class that will contain the extension:
<?php
namespace Acme\DemoBundle\Twig\Extension;
use Symfony\Component\DependencyInjection\ContainerInterface;
use \Twig_Extension;
class VarsExtension extends Twig_Extension
{
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function getName()
{
return 'some.extension';
}
public function getFilters() {
return array(
'json_decode' => new \Twig_Filter_Method($this, 'jsonDecode'),
);
}
public function jsonDecode($str) {
return json_decode($str);
}
}
Basically the $.getJson() method requires json but ther is a string
so you can use $.get() to get the response and use the parser to parse the string to JSON
$.get("ffff",function(data){
// user parser
JSON.parse();
});

Categories