How can I unmap a File input without using the form builder? - symfony

I have inherited an application that seems to have existed before the form builder existed. The developer kind of rolled his own with twig macros. Now I want to add a file upload to some existing forms, but I get what seems to be a well known error:
There was 1 error:
myBundle\Tests\Controller\snip\DefaultControllerUnitTest::testCanStoreDocumentAtS3
Exception: Serialization of
'Symfony\Component\HttpFoundation\File\UploadedFile' is not allowed
C:\apath\vendor\symfony\symfony\src\Symfony\Component\HttpKernel\DataCollector\DataCollector.php:27
C:\apath\vendor\symfony\symfony\src\Symfony\Component\HttpKernel\Profiler\Profiler.php:218
The solutions is to unmap the file field:
$builder->add('pic','file');
to this :
$builder->add('pic','file', array('mapped'=>false));
But in this case a builder is not used. Instead it looks like this:
{# file(name, value) #}
{% macro file(name, value) %}
<input type="file" name="{{ name }}" id="{{ name }}" value="{{ value }}" />
{% endmacro %}
Is there anything I can add to this macro, or do in the controller action to keep the Profiler from serializing this?

The answer was in part pilot error, but there is enough going on here that I hope I can help others avoid the same pitfall.
This error was triggered by a unit test where I was simulating a file upload along with other parameters. Initially the code that caused this error was:
$photo = new UploadedFile(
__DIR__ . '/TestReportMethod.xlsx',
'TestReportMethod.xlsx',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
123
);
....
$form['reportFile'] = $photo;
//submit
This caused the error in my original post.
After trying a few things I moved to this form instead.
$crawler = $this->client->request('POST',
$url,
array('id' => 328),
array('agencyInfoId' => 328),
array('reportFile' => $photo)
);
Which causes an InvalidArgumentException I think a little better example in the cookbook could have prevented. The correct form needs to be an array of parameter values, followed by an array of files:
$crawler = $this->client->request('POST',
$url,
array('id' => 328,
'agencyInfoId' => 328),
array('reportFile' => $photo)
);
I hope this helps somebody else!

Related

Cannot render text filtered with trans in twig template using Sandbox Security Policy

I am a little bit confused. First of all, look at my code, I guess.
public function renderTemplate($templateType, $data)
{
$layoutName = "$templateType.layout.html.twig";
$policy = new \Twig_Sandbox_SecurityPolicy(
['if', 'for', 'block', 'set', 'extends'],
['escape', 'format', 'dateformat', 'trans', 'raw', 'striptags'],
self::$allowedMethods,
self::$allowedProperties,
['gettext']
);
$sandboxExt = new \Twig_Extension_Sandbox($policy);
$intlExt = new \Twig_Extensions_Extension_Intl();
$i18nExt = new \Twig_Extensions_Extension_I18n();
$twig = new \Twig_Environment(new \Twig_Loader_Filesystem(__DIR__ . "/../Resources/views/Something/", "__main__"));
$sandboxExt->enableSandbox();
$twig->addExtension($sandboxExt);
$twig->addExtension($intlExt);
$twig->addExtension($i18nExt);
try {
$result = $twig->render($layoutName, $data);
} catch (\Exception $e) {
\Doctrine\Common\Util\Debug::dump($e);die();
}
return $result;
}
Here it is the template I want to render
{% extends 'layout.html.twig' %}
{% block title %}{{ entity.id }}{% endblock %}
{% block bodyTitle %}
{{ entity.id }} {{ 'translation_key.created_at'|trans({}, 'entities', locale) }} {{ entity.createdAt|dateformat(null, locale) }}
{% endblock %}
Here, as you can see, I want to render a template according to its type. The problem is: half of the template renders just fine, and then, when it tries to render the translated string, it throws an error.
Fatal error: Call to undefined function gettext() in /home/dev/vhosts/my-project/vendor/twig/twig/lib/Twig/Environment.php(403) : eval()'d code on line 69
I checked if this function existed right before trying to call render method, and it was really undefined. Basically, I have 2 questions here:
Question 1
How does it work in other parts of my project, but not in this specific handler? See "Important update" below.
Question 2
Can I solve my problem in another way? For example, without using Sandbox or using Sandbox with some kind of a flag "everythingAllowed=true"?
ATTENTION! IMPORTANT UPDATE
Previously, I misunderstood my own question. I thought the error was thrown while rendering the variable, but I re-checked the situation (When Alain Tiemblo asked me for twig template code here in comments) and now 100% sure it's thrown while trying to translate smth. Also, I have translations all over my project, and it works just fine, but in this specific situation it's not. I think it worth to mention, that I also tried to render the template without using Sandbox. I tried to render it directly from Twig Engine like this
return $this->templating->render($layoutName, $data);
//$this->templating is injected in the constructor via services.yml like this
//arguments:
// - "#templating"
The result - not properly translated text. When I dumped "locale" - I got one specific language, but the text was translated in another. But at least using this method - I didn't get any errors.. Can anybody clarify this for me? Because I really don't understand how the Intl/i18n extension works and why it doesn't want to work in Sandbox or not in Sanbox?
P.S. My guess, why it doesn't work directly from Twig Engine - probably I should inject not like "#templating" or it injects just right, but the Intl or I18n extensions are not enabled? How to enable. And I have no clues why it doesn't work with Sandbox

Symfony2 : How to upload a file without Doctrine?

I use Symfony2.3. I have a form like this :
<form action="{{ path("member_update") }}" method="post" {{ form_enctype(form) }}>
{{ form_widget(form.pic) }}
...
{{ form_widget(form._token) }}
</form>
and i want to upload user pictures in a directory.Then i use this in controller :
$member , $form , $dm is defined...
if ($form->isValid()) {
// Handle profile picture upload process
$uploadDir=dirname($this->container->getParameter('kernel.root_dir')) . '/web/bundles/mybundle/myfiles';
$form['pic']->getData()->move($uploadDir,$member->getId());
// End of upload
$dm->persist($member);
$dm->flush();
return $this->redirect($this->generateUrl("member_profile"));
}
It must work,but i see this error:
Exception: Serialization of 'Symfony\Component\HttpFoundation\File\UploadedFile' is not allowed
1. in pathToMyProject...\vendor\symfony\symfony\src\Symfony\Component\HttpKernel\DataCollector\DataCollector.php line 27
2. at serialize(.....
What's the problem??!
The problem solved! I change this line in MemberType :
$builder->add('pic','file');
to this :
$builder->add('pic','file', array('mapped'=>false));
My mistake was that i must explain the "pic" field is not mapped to the Entity(or Document in Mongo,as my project). Else Symfony kernel try to put the value of "pic" in a field of Entity. And i have not any field that hold a file! I upload the picture in a directory and store only path to the picture within the entity. When i changed this,the problem solved easily! :-)
So keep in mind to explain all things clearly to Symfony!

Symfony2 invalid token with big files

I'm having problem with token and file field form.
The validation of the form is like this:
public function getDefaultOptions(array $options)
{
$collectionConstraint = new Collection(array(
'fields' => array(
'file' => new File(
array(
'maxSize' => '2M',
'mimeTypes' => array(
'application/pdf', 'application/x-pdf',
'image/png', 'image/jpg', 'image/jpeg', 'image/gif',
),
)
),
)
));
return array(
'validation_constraint' => $collectionConstraint
}
When I upload a invalid size file(~5MB) I get this error which is what I hope:
The file is too large. Allowed maximum size is 2M bytes
But when I upload a too big file(~30MB) the error changes:
The CSRF token is invalid. Please try to resubmit the form
The uploaded file was too large. Please try to upload a smaller file
The problem is the error token. I've in my form the {{ form_rest(form) }} code. I think the error change is because of this: How to increase the upload limit for files on a Symfony 2 form?
I don't want to increase the upload limit. I want the token error doesn't show.
PHP (not Symfony) rejects the file if it is bigger than your configured values in:
post_max_size
upload_max_filesize
Because of this the csrf-error is thrown.
If you want to avoid this you have to increase the upload limit. It is the only way. If you add your file-constraint this should be no risk.
PROBLEM
CSRF token invalid & upload file too large errors
This two errors are form generated errors, and besides the field errors, they will appear when any exception occurs inside the form.
In this case of uploading files CSRF token invalid error appears due to post_max_size parameter in php.ini configuration file and
upload file too large error appears due to upload_max_filesize parameter in php.ini configuration file.
SOLUTION:
1- You can increase the value in the configuration files.
2- You can have field validation and comment or omit the line of form_errors inside your template.html.twig, notice that this solution will remove all kind of form generated errors notifications.
Example of template.html.twig:
<div class="form">
{{ form_start(form) }}
{{ form_errors(form) }} --> before
{# {{ form_errors(form) }} #} --> after
<div class="field">
{{ form_label(form.field) }}
{{ form_errors(form.field) }}
{{ form_widget(form.field) }}
</div>
{{ form_end(form) }}
</div>
In your Entity.php you need to specify the "maxSize" property to your Assert file.
For the exemple, the value "2147483648" equals 2GB.
/**
* #ORM\Column(type="string", length=255)
*/
public $path;
/**
* #Assert\File(maxSize="2147483648")
*/
public $file;

Symfony2: How use 'ckeditor' in a form?

I installed TRsteelCkeditorBundle, when I'm building in the view a form manually, it works.
<form method="post">
<p>
My Editor:<br>
<textarea name="editor1"><p>Initial value.</p></textarea>
<script>
CKEDITOR.replace( 'editor1' );
</script>
</p>
<p>
<input type="submit">
</p>
</form>
But when I try to use the Symfony2 form I get this error :
An exception has been thrown during the rendering of a template
("Route "route_name" does not exist.") in
lbTestBundle:Default:index.html.twig at line 8
My codes :
In the Twig template
{{ form_widget(form) }}
Ligne 8 is the form_widget
In the controller:
public function indexAction()
{
$formBuilder = $this->createFormBuilder();
$formBuilder
->add('date', 'date')
->add('title', 'text')
->add('content', 'ckeditor')
->add('author', 'text');
$form = $formBuilder->getForm();
$view['form'] = $form -> CreateView();
return $this->render('lbTestBundle:Default:index.html.twig', $view);
}
I followed step by step the indications of the Read_me.txt in he github page, and try to find answers elsewhere but found nothing. If someone can help me to solve that problem, i'm still beginner with SF2. Thanks
What is at lbTestBundle:Default:index.html.twig at line 8?
Obviously you have a route route_name in you template which is not defined in you routing.yml file.
That's all the error message says.
Same problem here. Spend all day today researching.
Finally, fixed it by replacing the TRsteelCkeditor bundle with the IvoryCKEditor bundle.
I found where the error comes from.
the route_name comes from
#config.yml for TrsteelCkeditor
filebrowser_image_browse_url:
route: route_name
route_parameters:
type: image
I suppose I have to put the route where the editor goes when you want to upload images in the editor.
I'll continue to test this budle till I got something fine and I'll give the result
Adding in comment the line
#route: route_name
In the config.yml solve the problem, this line is for uploading images on the server I think, see this link :
http://docs.cksource.com/CKEditor_3.x/Developers_Guide/File_Browser_(Uploader)
But now I am having some issues with language, I want to put it in French, at the moment the skin seems language dependent just like the hover on the buttons.
Also if you want to configure it, you can do it either in the config.yml or the config.js in /web/bundle repository if you already install the assets.

How do I use TrSteelCkEditorBundle in Symfony2?

I am new in the world of sf2 and I am trying to learn it.
I installed TrSteelCkEditorBundle with composer and now I am trying to get the editor in a view.
My bundle is active in the AppKernel.
As a beginner my question is:
What do I have to do to make it works?
I put this code and paste the value in the render
$form = $this->createFormBuilder()
->add('title', 'text')
->add('content', 'ckeditor', array(
'transformers' => array(),
))
->getForm();
And in the twig view i have line 6:
{{ form_widget(form) }}
but i'm getting an error :
An exception has been thrown during the rendering of a template ("Catchable Fatal Error:
Argument 1 passed to Symfony\Component\Form\FormRenderer::searchAndRenderBlock()
must be an instance of Symfony\Component\Form\FormView,
instance of Symfony\Component\Form\Form given, called in
/Applications/mamp/htdocs/Sf2/app/cache/dev/twig/5c/eb/e10823d760716de7f56b39640e79.php
on line 29 and defined in
/Applications/mamp/htdocs/Sf2/vendor/symfony/symfony/src/Symfony/Component/Form/FormRenderer.php
line 131") in amTestBundle:Default:index.html.twig at line 6.
If someone had a clue to resolve that it'll help me a lot.
Thank you.
The {{ form_widget(form) }} doesn't work because your $form variable is the form itself. In order to get Twig to create the widgets for it, you have to send it to the Twig template with:
$form->createView()
Here is an example of when you return in your controllerAction:
return $this->render(
'AcmeFooBundle:Acme:template.html.twig',
array('form' => $form->createView()) //Here you see the createView()
);

Resources