Twig: How can I manually escape inside a custom function? - symfony

I wrote my own Twig function that outputs HTML, so I have is_safe set to html so that Twig knows not to escape the output my function.
However, my function takes arguments. One of the arguments is placed in the output directly. I want to escape this before outputting it. So it seems I just need to be able to manually escape the option value before outputting it.
I can't find how to do this. Anyone know?

The trick is to store the twig enviroment which in turn is passed to twig_escape_filter
class TournExtension extends \Twig_Extension
{
protected $env;
public function initRuntime(\Twig_Environment $env)
{
parent::initRuntime($env);
$this->env = $env;
}
protected function escape($string)
{
return twig_escape_filter($this->env,$string);
}

Related

How to render a view from service class in symfony?

I'm trying to make a function in my service class, that render a twig page. I've tried to do like this:
service.yml:
********
parameters:
error.class: AppBundle\Utils\Error
services:
app.error:
class: '%error.class%'
arguments: [#templating]
Error.php (service class):
****
class Error
{
public function __construct($templating)
{
$this->templating = $templating;
}
public function redirectToError($condition,$message)
{
if($condition){
return $this->templating->render('default/error.html.twig',array(
'error_message' => $message,
));
}
}
}
and error.html.twig that have some random text to see if it gets there.
After that I get this answer from browser:
Can somebody to tell me what is the problem?
YAML can be a bit iffy when it comes to syntax, make sure your using all spaces (no tab chars). And makes sure every indentation is the same amount of space characters. Like 2/4/6/8 for each level or 4/8/12 etc if you prefer 4 wide.
The code you posted should be fine, but its probably something silly as described above. If it was actually a wrong section/ parameter in the file symfony should tell you what is unexpected as it actually validates YAML files on its content.
Allright so ['#templating'] takes care of the YAML parse error, the next part is how to use a service. Which is done using the service container.
In a controller there is an alias for it and you can do something like:
// required at the top to use the response class we use to return
use Symfony\Component\HttpFoundation\Response;
// in the action we use the service container alias
// short for $this->container->get('app.error');
$content = $this->get('app.error')->redirectToError(true, 'Hello world');
// as your redirectToError function returns a templating->render, which only returns a
// string containing the the rendered template, however symfony
// requires a Response class as its return argument.
// so we create a response object and add the content to it using its constructor
return new Response($content);
A few small things:
$condition, is probably likely to change if not it seems it should not be in the function but around the function call, as it seems weird to call an redirectToError but there is no error, instead we just call it when we do have an error.
And its recommended to if you are setting a class variable to define it (details on visibility):
class Error {
// visibility public, private, protected
protected $templating;
You should put ' around #templating
services:
app.error:
class: AppBundle\Utils\Error
arguments: ['#templating']

symfony 1.4 - how to reuse validate method across modules

I have a quite complex validate method in module1/actions.php called from module1/executeMyAction
I would like to reuse this in module2 rather than duplicate very similar code.
It feels like I should use a component or something like this but I don't need to call validate from a template I need to call it as part of the module1/executeMyAction or module2/executeMyAction so I can then set various variables for the executeMyActionSuccess.php template to handlle.
Can anyone let me know how I should reuse this validation code, I considered moving it into the form class but that just means I can't set the template variiables and it seems like it is breaking the MVC structure a bit so I'm not happy with that.
Would really appreciate any guidance.
If you want to share some parts of code between actions you can create a custom class which will implement some methods you need. You can put the class in the lib directory of either the application or the whole project.
E.g. create a apps/frontend/lib/myUtil.class.php
class myUtil
{
public static function addNumbers($a, $b)
{
return $a + $b;
}
}
Then in your action you can just use:
$sum = myUtil::addNumbers(2, 3);
If your code depends on some other objects it's best if you don't implement static methods but create an object of the class. E.g.
class myUtil
{
protected $request;
public function __construct(sfWebRequest $request)
{
$this->request = $request;
}
public function sumFromRequest()
{
return $this->request->getParameter('a') + $this->request->getParameter('b');
}
}
then in your action
public function executeSomething(sfWebRequest $request)
{
$util = new myUtil($request);
$this->sum = $util->sumFromRequest();
}
If your code is strictly used for validation of form fields you can create a custom validator which can be then used in your form. (which will definitely be the best solution). You can read about creating custom validators in the Symfony docs.

Using reflection in PHPUnit

I'm testing a private method of a class used in Symfony2 project with PHPUnit.
I'm using the private methods testing strategy (through reflection) described by many developers such as http://aaronsaray.com/blog/2011/08/16/testing-protected-and-private-attributes-and-methods-using-phpunit/
But unfortunately, I got the following error:
There was 1 error: 1) My\CalendarBundle\Tests\Calendar\CalendarTest::testCalculateDaysPreviousMonth
ReflectionException: Class Calendar does not exist /Library/WebServer/Documents/calendar/src/My/CalendarBundle/Tests/Calendar/CalendarTest.php:47
<?php
namespace My\CalendarBundle\Tests\Calendar;
use My\CalendarBundle\Calendar\Calendar;
class CalendarTest
{
//this method works fine
public function testGetNextYear()
{
$this->calendar = new Calendar('12', '2012', $this->get('translator'));
$result = $this->calendar->getNextYear();
$this->assertEquals(2013, $result);
}
public function testCalculateDaysPreviousMonth()
{
$reflectionCalendar = new \ReflectionClass('Calendar'); //this is the line
$method = $reflectionCalendar->getMethod('calculateDaysPreviousMonth');
$method->setAccessible(true);
$this->assertEquals(5, $method->invokeArgs($this->calendar, array()));
}
}
Why?
Thank you in advance
You need to use the whole namespaced class name when creating your reflection method, even if you include a use statement.
new \ReflectionClass('My\CalendarBundle\Calendar\Calendar');
This is because you are passing the class name as a string to the constructor, so it doesn't know about your use statement and is looking for the class name in the global namespace.
Also, for what it's worth, you don't actually need to create a ReflectionClass, then call getMethod() on it. Rather, you can directly create a ReflectionMethod object.
new \ReflectionMethod('My\CalendarBundle\Calendar\Calendar', 'calculateDaysPreviousMonth');
That should be essentially the same, but a bit shorter.

Trying to learn Flex function, vars and data flow

So I need to return the location or fname or what ever.... I would like to do this just by changing the pointer variable. I'm just comming from php to flex so I don't know what I'm doing -=) How can I do this?
public var myProfile:Object={
fname:"Deyon",
lname:"Smith",
age:"31",
loc:"New York"};
public var pointer:String="loc";
public function getProfileinfo():void{
trace(myProfile.pointer);
}
Thank you!
Change the following code:
function getProfileinfo(pointer:String):void{
trace(myProfile[pointer]);
}
Plus, you should put this code into a Class.

Is it possible to add behavior to a non-dynamic ActionScript 3 class without inheriting the class?

What I'd like to do is something like the following:
FooClass.prototype.method = function():String
{
return "Something";
}
var foo:FooClass = new FooClass();
foo.method();
Which is to say, I'd like to extend a generated class with a single method, not via inheritance but via the prototype.
The class is generated from a WSDL, it's not a dynamic class, and I don't want to touch the generated code because it will be overwritten anyway.
Long story short, I'd like to have the moral equivalent of C# 3:s Extension Methods for AS3.
Edit: I accepted aib's answer, because it fits what I was asking best -- although upon further reflection it doesn't really solve my problem, but that's my fault for asking the wrong question. :) Also, upmods for the good suggestions.
Yes, such a thing is possible.
In fact, your example is very close to the solution.
Try
foo["method"]();
instead of
foo.method();
#Theo: How would you explain the following working in 3.0.0.477 with the default flex-config.xml (<strict>true</strict>) and even a -compiler.strict parameter passed to mxmlc?
Foo.as:
package
{
public class Foo
{
public var foo:String;
public function Foo()
{
foo = "foo!";
}
}
}
footest.as:
package
{
import flash.display.Sprite;
public class footest extends Sprite
{
public function footest()
{
Foo.prototype.method = function():String
{
return "Something";
}
var foo:Foo = new Foo();
trace(foo["method"]());
}
}
}
Note that the OP said inheritance was unacceptable, as was modifying the generated code. (If that weren't the case, adding "dynamic" to the class definition would probably be the easiest solution.)
Depending on how many methods your class has, this may work:
Actual Class:
public class SampleClass
{
public function SampleClass()
{
}
public function method1():void {
Alert.show("Hi");
}
Quick Wrapper:
var actualClass:SampleClass = new SampleClass();
var QuickWrapper:Object = {
ref: actualClass,
method1: function():void {
this.ref.method1();
},
method2: function():void {
Alert.show("Hello!");
}
};
QuickWrapper.method1();
QuickWrapper.method2();
#aib is unfortunately incorrect. Assuming strict mode (the default compiler mode) it is not possible to modify the prototype of non-dynamic class types in ActionScript 3. I'm not even sure that it's possible in non-strict mode.
Is wrapping an option? Basically you create a class that takes one of the objects you get from the web service and just forwards all method calls to that, but also has methods of its own:
public class FooWrapper extends Foo {
private var wrappedFoo : Foo;
public function FooWrapper( foo : Foo ) {
wrappedFoo = foo;
}
override public function methodFromFoo( ) : void {
wrappedFoo.methodFromFoo();
}
override public function anotherMethodFromFoo( ) : void {
wrappedFoo.anotherMethodFromFoo();
}
public function newMethodNotOnFoo( ) : String {
return "Hello world!"
}
}
When you want to work with a Foo, but also have the extra method you need you wrap the Foo instance in a FooWrapper and work with that object instead.
It's not the most convenient solution, there's a lot of typing and if the generated code changes you have to change the FooWrapper class by hand, but unless you can modify the generated code either to include the method you want or to make the class dynamic I don't see how it can be done.
Another solution is to add a step to your build process that modifies the source of the generated classes. I assume that you already have a step that generates the code from a WSDL, so what you could do is to add a step after that that inserts the methods you need.
Monkey patching is an (inelegant) option.
For example, suppose you don't like the fact that Flex 3 SpriteAsset.as returns a default border metrics of [7,7,7,7] (unlike flex 2). To fix this, you can:
Create a copy of SpriteAsset.as and add it to your project at /mx/core/SpriteAsset.as
Edit your local copy to fix any problems you find
Run your ap
Google "flex monkey patch" for more examples and instructions.

Resources