Twig extension disable auto escape - symfony

I made a twig extension to be able to call functions in the templates, but unfortunately now the rendered html content of these functions is escaped. Do you have any idea how I could disable that?
FrontendTwigExtension.php
class FrontendTwigExtension extends Twig_Extension
{
/**
* #var DataProviderService
*/
private $dataProvider;
/**
* FrontendTwigExtension constructor.
* #param DataProviderService $dataProvider
*/
public function __construct(DataProviderService $dataProvider)
{
$this->dataProvider = $dataProvider;
}
/**
* #return array
*/
public function getFunctions(): array
{
return array(
new Twig_Function('getProductDetailData',
[$this, 'getProductDetailData'],
['needs_environment' => true]
),
new Twig_Function('getPageHeader',
[$this, 'getPageHeader'],
['needs_environment' => true]
)
);
}
/**
* #param Twig_Environment $env
* #return string
* #throws Twig_Error_Loader
* #throws Twig_Error_Runtime
* #throws Twig_Error_Syntax
*/
public function getPageHeader(Twig_Environment $env): string
{
return $env->render('Component/PageHeader/pageHeader.html.twig');
}
/**
* #param Twig_Environment $env
* #return string
* #throws Twig_Error_Loader
* #throws Twig_Error_Runtime
* #throws Twig_Error_Syntax
*/
public function getProductDetailData(Twig_Environment $env): string
{
$service = new ProductDetailDataService($this->dataProvider);
return $env->render('Module/ProductDetailPage/productDetailData.html.twig',
[
'productData' => $service->getData()
]
);
}
}
template.html.twig
{% extends 'base.html.twig' %}
{% block pageHeader %}
{{ getPageHeader() }}
{{ getProductDetailData() }}
{% endblock %}
services.yaml
App\Extension\FrontendTwigExtension:
arguments:
- '#App\DataProvider\DataProviderService'
tags:
- { name: 'twig.extension' }

You nedd to set the is_safe option:
['needs_environment' => true, 'is_safe' => ['html']]

Try using raw function in twig.
{% extends 'base.html.twig' %}
{% block pageHeader %}
{{ getPageHeader()|raw }}
{{ getProductDetailData()|raw }}
{% endblock %}
source: https://twig.symfony.com/doc/2.x/filters/raw.html

Related

My Symfony form errors are always global. Not linked to the specific field like supposed to

I have a Symfony form where I get errors when the fields are blanks.
I already try to set error_bubbling to false but it still not work (And is supposed to be false by default)
This is my code where I remove everything that is not necessary:
Controller:
/**
* #Route("/add", name="add")
*/
public function add(Request $request)
{
$post = new Post();
$form = $this->createForm(PostType::class, $post);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { } else { }
return $this->render('blog/add.html.twig', array('form' => $form->createView()));
}
Entity:
/**
* #ORM\Entity(repositoryClass="App\Repository\PostRepository")
* #ORM\HasLifecycleCallbacks()
*/
class Post
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
* #Assert\NotBlank
*/
private $Title;
/**
* #ORM\Column(type="text")
* #Assert\NotBlank
*/
private $Content;
...
FormType:
namespace App\Form;
use App\Entity\Post;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class PostType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('title')
->add('content');
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Post::class
]);
}
}
Form:
{% extends "base.html.twig" %}
{% block body %}
<h2>
Create a post
</h2>
{{ form_start(form) }}
{{ form_widget(form) }}
<input type="submit" class="btn" value="Create" />
{{ form_end(form) }}
{% endblock %}
When I look at the object after the post all the errors are linked to the form and there's no errors in the childs (The form fields).
Does anyone know what can be wrong?
In buildForm(), you need to capitalize your fields. They are case sensitive and they are capitalized in your database.

Twig_Error_Runtime an exception has been thrown during the rendering of a template

Object of class Proxies__CG__\AppBundle\Entity\Formation could not be converted to float
in vendor\easycorp\easyadmin-bundle\src\Resources\views\default\field_integer.html.twig (line 4)
{% if field_options.format %}
{{ field_options.format|format(value) }}
{% else %}
{{ value|number_format }}
{% endif %}
The error is fixed by commenting out my getters and setters for my foreign key in my entity i'm trying to set them up because they show inaccessible in my easy-admin Bundle
Entity code :
/**
* Questions
*
* #ORM\Table(name="questions", indexes={#ORM\Index(name="question_form_id", columns={"formid"})})
* #ORM\Entity
*/
/**
* #var \AppBundle\Entity\Formation
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Formation")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="formid", referencedColumnName="Form_id")
* })
*/
private $formid;
getters and setters :
/**
* #return Formation
*/
public function getFormid()
{
return $this->formid;
}
/**
* #param Formation $formid
*/
public function setFormid($formid)
{
$this->formid = $formid;
}
Fixed it, the #param was using the wrong column, sorry.

Assert does not works in my Form

I have a strange problem using a form in Symfony 3.
And my Assert does not works in my entity file.
In "the developer tools" it show the phrase but in the view all is in blank.
<?php
namespace TestBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* User
*
* #ORM\Table(name="users")
* #UniqueEntity("name")
* #UniqueEntity("email")
* #ORM\HasLifecycleCallbacks()
*/
class User implements UserInterface
{
/**
* #Assert\NotBlank()
* #Assert\NotBlank(message="Please enter your name.")
*/
private $name;
/**
* #Assert\NotBlank()
* #ORM\Column(type="string", length=50, nullable=false)
*/
private $sername;
/**
* #var string
* #Assert\NotBlank()
* #Assert\Email()
*/
private $email;
/**
* #var string
*/
private $password;
/**
* #var integer
*/
private $role;
/**
* #var \DateTime
*/
private $created;
/**
* #var integer
*/
private $id;
/**
* Set name
*
* #param string $name
*
* #return User
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set sername
*
* #param string $sername
*
* #return User
*/
public function setSername($sername)
{
$this->sername = $sername;
return $this;
}
/**
* Get sername
*
* #return string
*/
public function getSername()
{
return $this->sername;
}
/**
* Set email
*
* #param string $email
*
* #return User
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set password
*
* #param string $password
*
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set role
*
* #param integer $role
*
* #return User
*/
public function setRole($role)
{
$this->role = $role;
return $this;
}
/**
* Get role
*
* #return integer
*/
public function getRole()
{
return $this->role;
}
/**
* Set created
*
* #param \DateTime $created
*
* #return User
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created
*
* #return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
public function getRoles()
{
return array($this->role);
}
public function getSalt()
{
return null;
}
public function eraseCredentials()
{
}
/**
* Get username
*
* #return string
*/
public function getUsername()
{
return null;
}
}
My form Action ( I put required in false to use the symfony valid option):
public function addAction(Request $request){
$user = new User();
$form = $this->createFormBuilder($user)
->add('Name', TextType::class,array('required'=> false,'empty_data' => null))
->add('SerName', TextType::class,array('required'=> false,'empty_data' => null))
->add('role', TextType::class,array('required'=> false,'empty_data' => null))
->add('email', EmailType::class,array('required'=> false,'empty_data' => null))
->add('password', RepeatedType::class, array(
'type' => PasswordType::class,
'first_name' => 'pass',
'second_name' => 'confirm',
'required' => false,
))
->add('save', SubmitType::class, array('label' => 'Create Post'))
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//$user = new Users();
// $form->getData() holds the submitted values
// but, the original `$task` variable has also been updated
$password = $form->get('password')->getData();
$encoder = $this->container->get('security.password_encoder');
$encoded = $encoder->encodePassword($user,$password);
$user->setPassword($encoded);
$user = $form->getData();
// ... perform some action, such as saving the task to the database
// for example, if Task is a Doctrine entity, save it!
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
return $this->redirectToRoute('test_homepage');
}
//return $this->render('UserBundle:Default:add.html.twig');
return $this->render("TestBundle:Default:add.html.twig",array("form"=>$form->createView()));
}
EDIT (I PUT VIEW FILE):
My view:
{%extends "principal.html.twig"%}
{% block body %}
{{parent()}}
<h1> {% trans %}New User{% endtrans %}</h1>
{{ form_start(form,{'attr':{'novalidate':'novalidate','role':'form'}}) }}
{{ form_label(form.Name,'Username', {'label_attr': {'class': 'foo'}}) }}
{{ form_widget(form.Name,{'attr':{'class':'form-control'}}) }}
{{form_errors(form.Name)}}
{{ form_label(form.SerName,'Last name', {'label_attr': {'class': 'foo'}}) }}
{{ form_errors(form.SerName) }}
{{ form_widget(form.SerName,{'attr':{'class':'form-control'}}) }}
{{ form_label(form.role,'Role', {'label_attr': {'class': 'foo'}}) }}
{{ form_errors(form.role) }}
{{ form_widget(form.role,{'attr':{'class':'form-control'}}) }}
{{ form_label(form.email,'Email', {'label_attr': {'class': 'foo'}}) }}
{{ form_widget(form.email, {'attr':{'class':'form-control'}}) }}
{{ form_errors(form.email) }}
{{ form_label(form.password.pass, "Password", {'attr':{'class':'form-control'}}) }}
{{ form_errors(form.password) }}
{{ form_widget(form.password.pass, {'attr':{'class':'form-control'}}) }}
{{ form_label(form.password.confirm, "Confirm" , {'attr':{'class':'form-control'}}) }}
{{ form_widget(form.password.confirm, {'attr':{'class':'form-control'}}) }}
{{ form_widget(form.save, { 'label': 'Create User','attr':{'class':'btn btn-primary'}}) }}
{{ form_end(form) }}
{% endblock %}
You should read the doc about form rendering
In your twig template, you have to display the errors by using
{{ form_errors(form.age) }}
Or the whole row (label , error message, inpout) with
{{ form_row(form.age) }}
Which is almost equal to
<div>
{{ form_label(form.age) }}
{{ form_errors(form.age) }}
{{ form_widget(form.age) }}
</div>
In your case, it means you have to add form_errors this way:
{{ form_label(form.Name,'Username', {'label_attr': {'class': 'foo'}}) }}
{{ form_widget(form.Name,{'attr':{'class':'form-control'}}) }}
{{ form_errors(form.Name) }}

symfony2 get property values from form

i have a symfony entity called Config
class Config
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="key_name", type="string", length=255)
*/
private $keyName;
/**
* #var string
*
* #ORM\Column(name="key_value", type="text", nullable=true)
*/
private $keyValue;
/**
* #var string
*
* #ORM\Column(name="key_type", type="string", length=255)
*/
private $keyType;
/**
* #var string
*
* #ORM\Column(name="key_tab", type="string", length=255)
*/
private $keyTab;
controller :
class ConfigController extends Controller
{
/**
* Lists all Config entities.
*
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('MyBundle:Config')->findAll();
$configCollection = array('configs'=>$entities);
$collection = $this->createForm(new ConfigsType, $configCollection);
return $this->render('MyBundle:Config:index.html.twig', array(
'edit_form' => $collection->createView(),
));
}
view :
{% macro config_row(elem) %}
<div class="form-group">
{{ form_label(elem.keyValue, 'fff', { 'label_attr': { 'class': 'col-md-3 control-label' }}) }}
{# elem.keyName|humanize #}
<div class="col-md-4">
{{ form_widget(elem.keyValue, {'attr': { 'class': 'form-control input-large' }}) }}
{{ form_errors(elem.keyValue) }}
</div>
</div>
{% endmacro %}
<form action="{{ path('my_config') }}" method="post" {{ form_enctype(edit_form) }} >
{% for conf in edit_form.configs %}
{{ _self.config_row(conf) }}
{% endfor %}
</div>
{{ form_rest(edit_form) }}
</form>
what i need is for each config row i can get properties values in the config_row template to customize html rows structure based on their values
any idea please ?
thank you.
If I understand you correct you want to retrieve the value of each property of instance of entity Config, right?
If so, properties should be accessible by doing this:
{{ conf.vars.data.id }}
{{ conf.vars.data.keyName }}
{{ conf.vars.data.keyValue }}

Symfony2 error on render controller with relation OneToOne on same table

I have a problem to get a object from a controller called by the render controller method.
This is my Entity with the self OneToOne relation :
class Family
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToOne(targetEntity="Family")
* #ORM\JoinColumn(name="brother_id", referencedColumnName="id")
**/
private $brother;
/**
* #ORM\Column(type="string", length=100)
*/
private $label;
}
This is my action:
/**
* #Template()
*/
public function testAction()
{
$em = $this->getDoctrine()->getManager();
$brothers = $em->getRepository('FifaAdminBundle:Family')->findAll();
return array(
'brothers' => $brothers,
);
}
My view
{% for brother in brothers %}
{{ brother.id }} - {{ brother.label }}
<hr />
{% render controller('AdminBundle:Test:show', {'brother': brother}) %}
<hr />
{{ render(controller('AdminBundle:Test:show', { 'brother': brother })) }}
<hr />
{% endfor %}
My other controller
public function showAction($brother)
{
if (is_object($brother))
{
return new \Symfony\Component\HttpFoundation\Response('OK');
}
else
{
var_dump($brother);
return new \Symfony\Component\HttpFoundation\Response('KO');
}
}
The first element isgood.
But if it has a brother_id, this brother in not load by the showAction.
It gives me this:
array(1) { ["__isInitialized__"]=> string(1) "1" }
Please help me.
You probably want to use the #ParamConverter annotation in your case.
Your controller would go as follow:
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Admin\Bundle\Entity\Family;
/**
* #Route("/show/{id}")
* #ParamConverter("family", class="AdminBundle:Family")
*/
public function showAction(Family $brother)
{
//Do your stuff
}
And the view:
{% for brother in brothers %}
{{ brother.id }} - {{ brother.label }}
<hr />
{{ render(controller('AdminBundle:Test:show', { 'brother': brother.id })) }}
<hr />
{% endfor %}
Note that if no Family object is found, a 404 Response is generated. So you don't need to check if $brother is an object or not in your controller.
http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html
Thank you cheesemacfly
Indeed, it's work with the #ParamConverter
But it is wird because if I remove the OneToOne relation, it works without #ParamConverter

Resources