Create a simple twig filter - symfony

I get this error message when i create since i have created a simple twig filter. The message is not clear at all.
An exception has been thrown during the compilation of a template
("Warning: Illegal offset type in app/cache/dev/classes.php line
3342")
My filter:
class simpleFilter extends Twig_Extension
{
public function getFilters()
{
return array('simpleFilter' => new Twig_SimpleFilter($this, 'simpleFilter'));
}
public function simpleFilter($value)
{
return 'test'.$value;
}
public function getName()
{
return 'some_extension';
}
}
My config
my.twig.extension.simpleFilter:
class: Bundle\Twig\Filter\SimpleFilter
tags:
- { name: twig.extension }
Am i missing something?

Try to change your getFilters to look like this:
public function getFilters()
{
return array(
new Twig_SimpleFilter('simpleFilter', array($this, 'simpleFilter'))
);
}

I had to use Twig_Filter_Method
public function getFilters()
{
return array(
new Twig_Filter_Method('simpleFilter', array($this, 'simpleFilter'))
);
}
even if i do not know the difference beetween them.

Related

Custom Report SilverStripe 3.1

I followed the docs to create a custom report but keep failing to generate the report in the CMS. Has anyone else had this problem? I noticed that with older versions, the config had to include the report, but I see no sign of this in 3.1.
Here is the contents of CustomSideReport.php
class CustomSideReport_Day extends SideReport {
public function title() {
return "Event Calendar";
}
public function records() {
return Page::get()->sort("Title");
}
public function fieldsToShow() {
return array(
"Title" => array("NestedTitle", array("2"))
);
}
}
I have the done the usual dev/build and flush, but still nothing appears.
The documentation has now been updated to correctly show how to make custom site reports.
In SilverStripe 3.1 the class should extend SS_Report instead of SideReport.
Try this:
class CustomSideReport_Day extends SS_Report {
public function title() {
return 'Event Calendar';
}
public function sourceRecords($params = null) {
return Page::get()->sort('Title');
}
public function columns() {
$fields = array(
'Title' => 'Title'
);
return $fields;
}
}
Also note that records() has changed to sourceRecords($params = null) and fieldsToShow() has changed to columns().

filter boolean variable in a twig template

I have a boolean variable(0, 1) in my database and I want to filter it to a word 0 for 'NO', and 1 for 'Yes'. how can I do that in a twig template
I want something like {{ bool_var | '??' }} where the '??' is the filter
Quick way to achieve that is to use the ternary operator:
{{ bool_var ? 'Yes':'No' }}
http://twig.sensiolabs.org/doc/templates.html#other-operators
You could also create a custom filter that would do this. Read about custom TWIG extensions - http://symfony.com/doc/current/cookbook/templating/twig_extension.html
To build on what #dmnptr said in his last paragraph, in your app bundle, create a /Twig folder and create an AppExtension class inside.
class AppExtension extends \Twig_Extension
{
public function getFilters()
{
return array(
new \Twig_SimpleFilter('boolean', array($this, 'booleanFilter')),
);
}
public function booleanFilter($value)
{
if ($value) {
return "Yes";
} else {
return "No";
}
}
public function getName()
{
return 'app_extension';
}
}
Then, in your bundle's Resources/config/ folder, add the following to your services.yml where class is the class of the new class:
app.twig_extension:
class: [YourAppBundleNamespace]\Twig\AppExtension
public: false
tags:
- { name: twig.extension }
The filter will be available in Twig by simply appending a |boolean to any variable.
Or even better you could make a boolean to string transformer and add it to your form.
It might be 'more' code but the upside is reusability. You wouldn't have to make your templates dirty with logic and you could reuse it to all the forms you want :)
Pros:
Not tied to the form component so you can still use it.
Use it anywhere, more functionality than a twig extension.
No need to mess with twig or symfony configuration.
Can use it in forms themselves.
Documentation:
http://symfony.com/doc/current/cookbook/form/data_transformers.html
Example from:
Symfony2 Forms BooleanToStringTransformer Issue
<?php
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
class BooleanToStringTransformer implements DataTransformerInterface
{
private $trueValue;
private $falseValue;
public function __construct($trueValue, $falseValue)
{
$this->trueValue = $trueValue;
$this->falseValue = $falseValue;
}
public function transform($value)
{
if (null === $value) {
return null;
}
if (!is_bool($value)) {
throw new TransformationFailedException('Expected a Boolean.');
}
return true === $value ? $this->trueValue : $this->falseValue;
}
public function reverseTransform($value)
{
if (null === $value) {
return null;
}
if (!is_string($value)) {
throw new TransformationFailedException('Expected a string.');
}
return $this->trueValue === $value;
}
}

Exception when a twig extension service is used

I am trying to add functions to the twig gramework using twig extension.
this is the extension (I dont know if it works because I've had no opportunity to use it because of the problem I have :
class CnamtsStyleExtension extends \Twig_Extension {
protected $loader;
public function __construct(FilesystemLoader $loader)
{
$this->loader = $loader;
}
public function getFunctions()
{
return array(
'modal' => new \Twig_SimpleFunction($this, 'getModal', array('is_safe' => array('html')))
);
}
public function getModal($parameters=null) {
$template = htmlspecialchars($this->loader->getSource('component/modal.html.twig'));
return $this->getTemplateCode($template, $parameters===null ? null : json_decode($parameters));
}
protected function getTemplateCode($template, $parameters) {
$html_template = '';
if($parameters !== null) {
foreach ($parameters as $key => $value) {
$html_template = str_replace('{{' .$key. '}}', $value, $template);
}
}
return $html_template;
}
public function getName() {
return 'cnamts_style_extension';
}
}
Here is my service :
services:
cnamts.twig.cnamts_style_extension:
class: Cnamts\StyleGuideBundle\Twig\CnamtsStyleExtension
tags:
- { name: twig.extension }
arguments: ["#twig.loader"]
and the twig :
{% extends "::base.html.twig" %}
{% block body %}
Hello world
{% endblock %}
as you can see, my twig does not use any function of my extension. it is just a simple 'hello world'.
So I clear the cache (even manually to be sure), and I send the route....
I have two exceptions :
Exception number 1 in my twig:
ContextErrorException: Warning: Illegal offset type in my_project\vendor\twig\twig\lib\Twig\Environment.php line 1167
Exception number 2: even the web tool bar cannot display and there is a 500 error from the server
Illegal offset type "#WebProfiler/Collector/config.html.twig
but coming originally from the same exception in Environment.php
I am sure it is linked to the extension because when I deactivate the service I have added, there are no errors
Thank you for you help;
PS : I could debug and see that the loader is not null or whatever (it seems good)... my class is the problem because I tried to load the same service giving another class extension and I dont have the problem.
Try to use this
public function getFunctions(){
return array(
'getmodal' => new \Twig_Function_Method($this, 'getModal');
);
}

Creating my first twig extension to provide global variables to base templates

I need to populate a variable with some HTML code and make it available to my base.html.twig file.
To achive this I have made a twig extension. This is my first time using twig extentions so im not sure if this is the correct way of doing things.
Here is what I have so far:
Extension code:
class GlobalFooterExtension extends \Twig_Extension
{
public function getFilters()
{
return array(
new \Twig_Filter_Function('GlobalFooter', array($this, 'GlobalFooter')),
);
}
public function GlobalFooter()
{
$GlobalFooter = file_get_contents('http://mysite.co.uk/footer/footer.html.twig');
return $GlobalFooter;
}
public function getName()
{
return 'GlobalFooter_extention';
}
}
config.yml:
services:
imagine.twig.GlobalFooterExtension:
class: Imagine\GdmBundle\Twig\GlobalFooterExtension
tags:
- { name: twig.extension }
base.html.twig:
{{GlobalFooter}}
This give the following error:
Twig_Error_Runtime: Variable "GlobalFooter" does not exist in "ImagineGdmBundle:Default:product.html.twig" at line 2
Im sure im missing something really obvious. How do I make $GlobalFooter from my GlobalFooterExtension class available to my base.hmtl.twig file?
You want to set a global variable, not a function.
Just use getGlobals and return your variable:
class GlobalFooterExtension extends \Twig_Extension
{
public function getGlobals()
{
return array(
"GlobalFooter" => file_get_contents('http://mysite.co.uk/footer/footer.html.twig'),
);
}
public function getName()
{
return 'GlobalFooter_extention';
}
}
Or, if you want to lazy load the value of the variable, create a function and change your template to:
{{ GlobalFooter() }}
Besides this, if the footer file is on the same site, it's better to use the {% include '...' %} tag.
rename function getFilters to getFunctions

Not able to call dependent test cases

I am writing the unit tests to test a Model class.
First I have a testAddStudent() test case that adds some data to db.
Then I have another test case to retrieve the record I just added.
The code I have looks like the following:
class Model_STest extends PHPUnit_Framework_TestCase {
protected $_student;
public function setUp() {
error_log("Entered setup");
parent::setUp();
$this->_student = new Application_Model_Student();
}
public function testInit() {
error_log("Entered testInit");
}
public function testAddStudent() {
error_log("Entered testAddStudent");
$testData = array(
'name' => 'abc',
'teacher' => 'amyac',
'start_date' => '2012_08_06'
);
$result = $this->_student->addStudent($testData);
error_log("result is ".print_r($result, true));
$this->assertGreaterThan(0, $result);
}
/**
* #depends testAddStudent
*/
public function testGetStudent($result) {
error_log("Entered testGetStudent, finding student id: $result");
$resultx = $this->_student->getStudent($result);
$this->assertEquals($result, $resultx);
}
}
However, when I run the phpunit test (using command line), The logs show me that the student id being searched is 0. Whereas the testAddStudent is returning me the student id as a non-zero value.
What am I doing wrong?
I have
PHPUnit 3.6.11 by Sebastian Bergmann.
Any help is greatly appreciated.
Thanks!
You should return $result from your testAddStudent() function.
(The returned value from the depended-on function is passed to depending function.)
You might also consider doing the same with your Application_Model_Student instance, instead of using a protected class variable. Here is your example rewritten to show that. (I used a dummy Application_Model_Student that does just enough to pass the test.)
class Application_Model_Student{
private $d;
function addStudent($d){$this->d=$d;return 1;}
function getStudent($ix){return $ix;}
}
//----------------------
class Model_STest extends PHPUnit_Framework_TestCase {
public function testAddStudent() {
error_log("Entered testAddStudent");
$testData = array(
'name' => 'abc',
'teacher' => 'amyac',
'start_date' => '2012_08_06'
);
$student = new Application_Model_Student();
$result = $student->addStudent($testData);
error_log("result is ".print_r($result, true));
$this->assertGreaterThan(0, $result);
return array($student,$result);
}
/**
* #depends testAddStudent
*/
public function testGetStudent($data) {
list($student,$result)=$data;
error_log("Entered testGetStudent, finding student id: $result");
$resultx = $student->getStudent($result);
$this->assertEquals($result, $resultx);
}
}
P.S. Note the implementation I used for getStudent to get it to pass! I imagine this is not the test you intended to do.

Resources