I'm using twig 1.12.2. My code generates some elements from code-behind, when rendering these with the latest version of twig they get html-encoded
{% for item in files_folders %}
<tr class="{{ cycle(['tr_odd', 'tr_even'], loop.index) }}">
<td><img src="../templates/images/sharepoint/{{ item.ContentType }}.gif" border="0" alt=""/></td>
<td>{{ item.Link }}</td>
<td>{{ item.Modified }}</td>
<td>{{ item.FileSize }}</td>
<td>{{ item.FileType }}</td>
</tr>
{% endfor %}
This will output this
<tr class="tr_even">
<td><img src="../templates/images/sharepoint/Document.gif" border="0" alt=""/></td>
<td><a href='?download=/ddd.png'>ddd.png</a></td>
<td>2013-03-04 17:47:38</td>
<td>64.8 KB</td>
<td>png</td>
</tr>
<tr class="tr_odd">
<td><img src="../templates/images/sharepoint/Document.gif" border="0" alt=""/></td>
<td><a href='?download=/asdasd.png'>asdasd.png</a></td>
<td>2013-03-03 20:01:52</td>
<td>66.04 KB</td>
<td>png</td>
</tr>
When I debug and have a look at the data before it's sent to twig it is not escaped. I haven't found any alternative to {{ item.Link }} to render data as-is.
Thanks
You can use the raw filter to make twig render raw html
http://twig.sensiolabs.org/doc/filters/raw.html
{% autoescape %}
{{ var|raw }} {# var won't be escaped #}
{% endautoescape %}
You should be careful with using |raw. Saying that the data is safe, means you are trusting it 100%.
Personally I would suggest using a custom twig filter:
class CustomExtension extends \Twig_Extension
{
public function getFilters()
{
return array(
new \Twig_SimpleFilter('unescape', array($this, 'unescape')),
);
}
public function unescape($value)
{
return html_entity_decode($value);
}
}
Add the following to your services.yml (or alternatively translate into xml).
services:
ha.twig.custom_extension:
class: HA\SiteBundle\Twig\CustomExtension
tags:
- { name: twig.extension }
Or http://twig.sensiolabs.org/doc/filters/raw.html
{% autoescape false %}
{{ your_item }}{# your_item won't be escaped #}
{% endautoescape %}
If you are using Drupal 8 and none of raw or autoscape works, this could happen because of the variable you're trying to print if it's a render array with a template holding a safe output (for example, a hl2br filter).
I that case, you would need to access the value through the render array and filter it, for instance:
{% autoescape false %}
{{ item.content['#context']['value'] }}
{% endautoescape %}
Related
search over this in google and looked the official docs of twig, didn't find an answer,
I have this
$data['count'] = $count;//6
in my php code,
I want to generate td as much as the $beltCount in the twig file I tried this but it didn't work:
{% for i in count%}
<td> {{ i }}</td>
{% endfor %}
Should I do this in a different way? I didn't find a syntax for this
Thanks
The integer 6 isn't enumerable, it's just a number.
You can however use range(1, count) or, as stated Teneff in comments, the range operator 1..count to create an enumerable from 1 to 6 (or whatever value is in count) :
{% for i in range(1, count) %}
<td> {{ i }}</td>
{% endfor %}
{% for i in 1..count %}
<td> {{ i }}</td>
{% endfor %}
fiddle
You will find more infos in the documentation
I use form theme like it is explain in the documentation https://symfony.com/doc/current/form/form_themes.html with :
{% form_theme form.methodes 'form_table_layout.html.twig' %}
In order to have table and not "div".
My problem is :
For a normal form with "div", i use this code to modify and adapt a collection :
{% block _Examplebundle_methodes_entry_widget %}
Documentation "How to Customize a Collection Prototype" : https://symfony.com/doc/3.4/form/form_customization.html
It work for theme with "div" but with the theme 'form_table_layout.html.twig' it didn't work. I don't know how to custom block with the table theme.
here is a part of my code :
{% form_theme form.methodes 'form_table_layout.html.twig' %}
//////// Block to custom the collection/////////////
{% block _Examplebundle_methodes_entry_widget %}
<tr>
<td>
{{ form_widget(form.methodeEssai) }}
{{ form_errors(form.methodeEssai)}}
</td>
<td>
{{ form_widget(form.ind, {'attr' : {'placeholder' : 'Index'}}) }}
{{ form_errors(form.ind)}}
</td>
<td>a</td>
<td>z</td>
<td>e</td>
<td>r</td>
<td>t</td>
</tr>
{% endblock %}
//////// End Block custom /////////////
{% block body %}
{{ form_start(form) }}
....
<table id="eagle_laboratorybundle_pvp_methodes" class="row"
data-prototype="
{{form_widget(form.methodes.vars.prototype)|e('html_attr') }}"
data-index="{{ form.methodes|length }}">
<thead>
<tr>
<th>x</th>
<th>y</th>
<th>z</th>
<th>a</th>
<th>r</th>
<th>e</th>
<th>t</th>
</tr>
</thead>
<tbody>
{{ form_widget(form.methodes) }}
{{ form_errors(form.methodes) }}
</tbody>
</table>
/// Some JS etc...///
So with the block _entry_widget i expected to custom rows of my table like it permit to custom div when i'm using original layout theme.
Someone know how to custom form rendering with table theme ?
I am trying to implement a search for user by email function into page admin's dashboard. Currently, I have hardcoded a value into $email variable just to test whether the search works. It does find the right user, but does not display anything in the twig.
Executing {{ dump() }} outputs: array:2 [▼ 0 => User {#4745 ▼ -id: 5 -
username: "test_user" -plainPassword: null -password:
"$2y$13$rGYteIrzifg9Dty.O5knOOCHQnzOtF.nZux8h1jc4sNbap5V7Xn0." -email:
"tester#test.com" } "app" => AppVariable {#2617 ▶} ]
the function I use in AdminController.php:
/**
* #Route("/admin/result", name="user_search")
* Method({"POST"})
*/
public function user_search(Request $request)
{
$email = 'tester#test.com';
$result = $this->getDoctrine()
->getRepository(User::class)
->findOneBy(['email' => $email]);
if ($result) {
return $this->render('admin/result.html.twig', $result);
}else{
return $this->render('admin/result.html.twig', [
'error' => 'No user found with this email '.$email]);
}}
result.html.twig:
{% extends 'base.html.twig' %}
{% block body %}
{% if error %}
<span class="error">{{ error }}</span>
{% endif %}
{% if result %}
<table>
<tr>
<th>Username</th><th>Email</th>
</tr>
{% for item in result %}
<tr>
<td>{{ item.getUsername }}</td><td>{{ item.getEmail }}
</td>
</tr>
{% endfor %}
</table>
{% endif %}
{{ dump() }}
{% endblock %}
In twig you assume that the result is an array. For this, uses findBy instead of findOneBy. findBy returns an array of objects with the desired search. The findOneBy return only an object with the desired search or null if results are not found.
Example:
// look for a single User by email
$result = $this->getDoctrine()
->getRepository(User::class)
->findOneBy(['email' => $email]);
// look for multiple User objects matching the email
$result = $this->getDoctrine()
->getRepository(User::class)
->findBy(['email' => $email]);
This was finally solved by these steps:
There was a typo in the hardcoded $email variable.
Changed return $this->render('admin/result.html.twig', 'result'->$result); instead of return $this->render('admin/result.html.twig', $result);
Changed <td>{{ item.username }}</td><td>{{ item.email }}</td> instead of <td>{{ result.getUsername }}</td><td>{{ result.getEmail }}</td>
Check $user with instance
if ($result instanceof User)
.......................................................................
I suggest you use defined in twig
{% if result is defined %}
{% extends 'base.html.twig' %}
{% block body %}
{% if error is defined %}
<span class="error">{{ error }}</span>
{% else %}
<table>
<tr>
<th>Username</th><th>Email</th>
</tr>
{% for item in result %}
<tr>
<td>{{ result.getUsername }}</td><td>{{ result.getEmail }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
{% endblock %}
My code is aimed at getting items from database. Those item may have either debit values or credit values. In template I present all of the values but would like also to provide information about sum of debit and account values connected with the account ($account_id)
What would be your best practice how to do this?
Should I simply run another two SQL queries:
first to SUM(value) where accountdebet = '.$account_id
secound to SUM(value) where accountcredit = '.$account_id?
Will it be the right approach?
Controller:
// Get items for acccount and paginate
$rp_items = $this->getDoctrine()->getManager()->getRepository('AppBundle:Items');
$query = $rp_items->createQueryBuilder('p')
->where('p.accountdebet = '.$account_id)
->orWhere('p.accountcredit = '.$account_id)
->getQuery();
$rp_paginator = $this->get('knp_paginator');
$db_pagination = $rp_paginator->paginate($query,$this->get('request')->query->getInt('page', 1),10);
// Render TPL
return $this->render('AppBundle:Accounts:items.html.twig', array('pagination' => $db_pagination, 'account' => $account));
In twig:
{% extends '::base.html.twig' %}
{% block body %}
<B>Item list for account {{ account.id }} </B><BR>
Account id: {{ account.id }}<BR>
Account marker: {{ account.marker }}<BR>
Account name: {{ account.name }}<BR>
<table class="table table-striped">
<tr>
{# sorting of properties based on query components #}
<th>{{ knp_pagination_sortable(pagination, 'Id', 'a.id') }}</th>
<th{% if pagination.isSorted('a.itemdate') %} class="sorted"{% endif %}>{{ knp_pagination_sortable(pagination, 'Date', 'a.itemdate') }}</th>
<th>Document</th>
<th>{{ knp_pagination_sortable(pagination, 'Marker', 'a.marker') }}</th>
<th>Debit</th>
<th>Credit</th>
</tr>
{# table body #}
{% for item in pagination %}
<tr>
<td>{{ item.id }}</td>
<TD>{{ item.itemdate|date('Y-m-d')}}</TD>
<td>{{ item.documentid.marker }}</td>
<td>{{ item.marker }}</td>
<TD>{% if item.accountdebet.id == account.id %}
{{ item.itemvalue}}
{% endif %}
</TD>
<TD>{% if item.accountcredit.id == account.id %}
{{ item.itemvalue}}
{% endif %}</TD>
</tr>
{% endfor %}
</table>
{# display navigation #}
<div class="pagination">
{{ knp_pagination_render(pagination) }}
</div>
{% endblock %}
You can solve it in many ways but i like to make an parent entity eg ItemsCollection that holds an arrayCollection of Items. Then i give the new entity some extra functionality e.g.
public function countItemValues()
{
$total = 0;
foreach($this->items as $item)
{
$total += $item->getValue();
}
return $total;
}
I have a custom validator on my Symfony2 project.
The validation works fine, but the method is somehow accessed twice.
Here is my custom validator: My other resolved question
The problem is the next:
As you can see, the error message is displayed twice. When I am trying to var dump something in the validate method, the vardump is also displayed twice. Any idea why the validate is called twice? This is called when I am using $form->bind($request); in my controller.
EDIT
Here is the twig template:
{% extends 'MerrinMainBundle::layout.html.twig' %}
{% block page_title %}
MDPI Conversion system (Merrin) 3.0 - New Conversion
{% endblock %}
{% block main %}
{% for flashMessage in app.session.flashbag.get('user-notice') %}
<div class="flash-notice">
{% autoescape false %}
{{ flashMessage }}
{% endautoescape %}
</div>
{% endfor %}
<h1>Create New Manuscript</h1>
{% if valid == false %}
<div class="error">
{{ form_errors(form) }}
{{ form_errors(form.doi) }}
{{ form_errors(form.publisher) }}
{{ form_errors(form.file) }}
</div>
{% endif %}
<form action="{{ path }}" method="POST" {{ form_enctype(form) }}>
</form>
{% endblock %}
And the controller call
public function createAction()
{
$em_scipub = $this->getDoctrine()->getManager();
$em_mdpipub = $this->getDoctrine()->getManager('mdpipub');
$enquiry = new Manuscript();
$formType = new NewManuscriptType();
$form = $this->createForm($formType, $enquiry);
$request = $this->getRequest();
$valid = true;
$error = '';
if ($request->isMethod('POST')) {
$form->bind($request);
if ($form->isValid()) {
... do something ...
$em_scipub->persist($enquiry);
$em_scipub->flush();
$flash_message = "<a href='edit/".$enquiry->getId()."'>New Manuscript</a> sucessfully created.";
$this->get('session')->getFlashBag()->set('user-notice', $flash_message);
return $this->redirect($this->generateUrl('MerrinMainBundle_new'));
}
else
$valid = false;
}
$path = $this->generateUrl('MerrinMainBundle_new');
return $this->render('MerrinMainBundle:Pages:new_conversion.html.twig.twig', array(
'valid' => $valid,
'path' => $path,
'form' => $form->createView(),
) );
}
EDIT2:
The validate function:
public function validate($value, Constraint $constraint)
{
$doi = $value->getDoi();
preg_match('/[^\/]+/i', $doi, $publisherDoiAbbr);
if($publisherDoiAbbr[0] !== $value->getPublisher()->getDoiAbbreviation()) {
$this->context->addViolation($constraint->message_publisher_DOI);
}
else {
preg_match("/[a-z]+/",$doi, $journalDoiAbbr);
$em_mdpipub = $this->entityManager;
$journal = $em_mdpipub->getRepository('MerrinMdpiPubBundle:Journal')->findOneBy(array('doi_abbreviation' => $journalDoiAbbr));
if($journal == null) {
$this->context->addViolation($constraint->message_journal_DOI);
}
}
preg_match('/\d*$/i', $doi, $doiNumericPart);
if(strlen($doiNumericPart[0]) < 8) {
$this->context->addViolation($constraint->message_volume_issue_firstpage_DOI);
}
}
And the twig template:
{% extends 'MerrinMainBundle::layout.html.twig' %}
{% block page_title %}
MDPI Conversion system (Merrin) 3.0 - New Conversion
{% endblock %}
{% block main %}
{% for flashMessage in app.session.flashbag.get('user-notice') %}
<div class="flash-notice">
{% autoescape false %}
{{ flashMessage }}
{% endautoescape %}
</div>
{% endfor %}
<h1>Create New Manuscript</h1>
{% if valid == false %}
<div class="error">
{{ form_errors(form) }}
{{ form_errors(form.doi) }}
{{ form_errors(form.publisher) }}
{{ form_errors(form.file) }}
</div>
{% endif %}
<form action="{{ path }}" method="POST" {{ form_enctype(form) }}>
<div style="float:left;">
<table width="700">
<tr>
<td>
{{ form_label(form.doi) }}
</td>
<td>
{{ form_widget(form.doi, { 'attr': {'size': 40} }) }}
</td>
</tr>
<tr>
<td>
{{ form_label(form.publisher) }}
</td>
<td>
{{ form_widget(form.publisher) }}
</td>
</tr>
<tr>
<td>
{{ form_label(form.file) }}
</td>
<td>
{{ form_widget(form.file) }}
</td>
</tr>
<tr>
<td>
</td>
<td>
<input class="submit-confirm-button" type="submit" name="update-text" value="submit" />
<a class="cancel-link" href="{{ path('MerrinMainBundle_homepage' ) }}">Cancel</a>
</td>
</tr>
</table>
</div>
{{ form_rest(form) }}
</form>
{% endblock %}
EDIT 3:
Here is how I am applying the validator to the entity:
/**
* Manuscript
*
* #IsDOI()
* #ORM\Table(name="manuscripts")
* #ORM\Entity(repositoryClass="Merrin\MainBundle\Repository\ManuscriptRepository")
* #ORM\HasLifecycleCallbacks
*
*/
class Manuscript
{
....
}
EDIT 4:
When I try to vardump the
$form->getErrors();
I am getting an array with two values:
array(2) {
[0]=>
object(Symfony\Component\Form\FormError)#507 (4) {
["message":"Symfony\Component\Form\FormError":private]=>
string(77) "The Publisher DOI abbreviation does not correspond to the DOI you filled in !"
["messageTemplate":protected]=>
string(77) "The Publisher DOI abbreviation does not correspond to the DOI you filled in !"
["messageParameters":protected]=>
array(0) {
}
["messagePluralization":protected]=>
NULL
}
[1]=>
object(Symfony\Component\Form\FormError)#542 (4) {
["message":"Symfony\Component\Form\FormError":private]=>
string(77) "The Publisher DOI abbreviation does not correspond to the DOI you filled in !"
["messageTemplate":protected]=>
string(77) "The Publisher DOI abbreviation does not correspond to the DOI you filled in !"
["messageParameters":protected]=>
array(0) {
}
["messagePluralization":protected]=>
NULL
}
}
This is possible if you are using validation groups and apply validator to several groups. And what #IsDOI() annotation mean? If its apply validation possible that you first add validator in validation.yml and second via this custom annotation.
The problem is that you're rendering it twice.
Here:
{{ form_errors(form) }}
followed by:
{{ form_errors(form.doi) }}
{{ form_errors(form.publisher) }}
{{ form_errors(form.file) }}
Since you are displaying the errors in single place, I recommend using only the first method.
As stated in the form_errors twig reference:
form_errors(view)
Renders any errors for the given field.
{{ form_errors(form.name) }}
{# render any "global" errors #}
{{ form_errors(form) }}
Since you have a lot of custom code (EntityManager, Validator) it is hard to tell the error with the amount of code you provide because it's not possible to recreate the error locally.
But here are my suggestions:
In your Validator there are two possible cases the following violation gets thrown
$this->context->addViolation($constraint->message_publisher_DOI);
On both occasions the error message is the same. Maybe both of these cases apply. Try to debug this by adding an individual error message for both cases.
I don't know the code of your Form-Class but maybe you apply your custom validator to multiple fields? Also remove validations for each field individually to see where the duplicate error message is thrown.
One last mistake I can imagine would be a custom Form-Template. If you have one check whether or not you maybe call the {{ form_error(form) }} block or any other block multiple times.
I hope one of my suggestions did help you.