Symfony3 Image validation for working - php

If I don't validate what I am uploading things work fine but the moment I add validation to the image field I get an error of
Serialization of 'Symfony\Component\HttpFoundation\File\UploadedFile' is not allowed
The only thing at the moment I have inside my validation.yml is as following
AppBundle\Entity\User:
properties:
firstName:
- NotBlank: {message: "user.firstname.not_blank"}
lastName:
- NotBlank: { message: "user.lastname.not_blank" }
profileImage:
- Image:
Inside my Entity
use Symfony\Component\HttpFoundation\File\File;
public function setProfileImage(File $profileImage = null)
{
$this->profileImage = $profileImage;
return $this;
}
What am I missing here? This used to work fine in Symfony 2.7

Related

Sonata Media - file extension validation in admin

I just want to validate the extension of image that I upload in Sonata Admin (v3.28.0) with Sonata Media Bundle (v3.10.0) in Symfony (v2.8.32) application.
I've read all similar questions and Sonata documentations, but still don't have a success.
I tried to add constraints to config.yml
sonata_media:
providers:
image:
allowed_extensions:
- 'jpg'
- 'png'
I wonder that it doesn't work as is, because standard FileProvider (that is extended by ImageProvider) has extension check in validate method. But the method is not being called.
So I also tried to create custom provider:
services.yml:
sonata.media.provider.custom:
class: Application\Sonata\MediaBundle\Provider\CustomImageProvider
tags:
- { name: sonata.media.provider }
arguments:
- sonata.media.provider.custom
- #sonata.media.filesystem.local
- #sonata.media.cdn.server
- #sonata.media.generator.default
- #sonata.media.thumbnail.format
- ['jpg', 'png']
- ['image/pjpeg', 'image/jpeg', 'image/png', 'image/x-png']
- #sonata.media.adapter.image.imagick
- #sonata.media.metadata.proxy
calls:
- [ setTemplates, [{helper_view:SonataMediaBundle:Provider:view_image.html.twig,helper_thumbnail:SonataMediaBundle:Provider:thumbnail.html.twig}]]
Application\Sonata\MediaBundle\Provider\CustomImageProvider.php:
<?php
namespace Application\Sonata\MediaBundle\Provider;
use Sonata\CoreBundle\Validator\ErrorElement;
use Sonata\MediaBundle\Model\MediaInterface;
use Sonata\MediaBundle\Provider\ImageProvider;
class CustomImageProvider extends ImageProvider
{
public function validate(ErrorElement $errorElement, MediaInterface $media)
{
throw new \Exception();
}
}
config.yml:
sonata_media:
contexts:
image:
providers:
- sonata.media.provider.custom
formats:
small: { width: 100 , quality: 70}
big: { width: 500 , quality: 70}
But the validate method is still not being called.
So when I try to load GIF image I get an error:
Length of either side cannot be 0 or negative, current size is x
Do I miss something?
UPDATE
Simple validation can be added right in SomeEntityAdmin class like this:
public function validate(ErrorElement $errorElement, $object)
{
/** #var Media $image */
$image = $object->getImage();
if (!in_array($video->getContentType(), ['image/pjpeg', 'image/jpeg', 'image/png', 'image/x-png'])) {
$errorElement
->with('image')
->addViolation('Invalid file type')
->end()
;
};
}
But it's not a good solution if you want to validate a batch of uploaded images.

OneupUploaderBundle(blueimp) - save file

I have problem with configure blueimp. When I send file (click: start upload) in jsconsole is:
POST XXXapp_dev.php/_uploader/gallery/upload 500 (Internal Server
Error)
I used:
Simple example of the entity file to be uploaded with OneupUploaderBundle
https://github.com/1up-lab/OneupUploaderBundle/issues/51#issuecomment-24878715
My file:
services.yml:
Cms.upload_listener:
class: Cms\AdminBundle\EventListener\UploadListener
arguments: [#doctrine]
tags:
- { name: kernel.event_listener, event: oneup_uploader.post_upload, method: onUpload }
config.yml:
oneup_uploader:
mappings:
gallery:
frontend: blueimp
storage:
service: ~
type: filesystem
filesystem: ~
directory: web/uploads/gallery
stream_wrapper: ~
sync_buffer_size: 100K
routing.yml
oneup_uploader:
resource: .
type: uploader
~Entity/File.php
/* ... */
/**
* #ORM\Entity
* #ORM\Table(name="file")
*/
class file {
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string")
*/
protected $filename;
}
~/EventListner/UploadListner.php
class UploadListener
{
protected $manager;
public function __construct(EntityManager $manager)
{
$this->manager = $manager;
}
public function onUpload(PostPersistEvent $event)
{
$file = $event->getFile();
$object = new file();
$object->setFilename($file->getPathName());
$this->manager->persist($object);
$this->manager->flush();
}
}
debug route:
_uploader_upload_gallery POST ANY ANY
/_uploader/gallery/upload
Directory /web/uploads/gallery is on the server.
What am I trying to achieve? I need upload files to server and add record to db.
I think that config is incorrect, but where?
Edit 1:
Maybe help
INFO - An exception was thrown while getting the uncalled listeners
(Catchable Fatal Error: Argument 1 passed to
Cms\AdminBundle\EventListener\UploadListener::__construct() must be an
instance of Cms\AdminBundle\EventListener\EntityManager, instance of
Doctrine\Bundle\DoctrineBundle\Registry given, called in
/home/cms/public_html/app/cache/dev/appDevDebugProjectContainer.php on
line 455 and defined) Context:
{"exception":"Object(Symfony\Component\Debug\Exception\ContextErrorException)"}
CRITICAL - Uncaught PHP Exception
Symfony\Component\HttpFoundation\File\Exception\FileException: "Unable
to create the "/uploads/gallery" directory" at
/home/cms/public_html/vendor/symfony/symfony/src/Symfony/Component/HttpFoundation/File/File.php
line 134 Context:
{"exception":"Object(Symfony\Component\HttpFoundation\File\Exception\FileException)"}
I created uploads/gallery! chmod 777. I don't understand.
Edit 2:
Cms.upload_listener:
class: Cms\AdminBundle\EventListener\UploadListener
arguments: ["#doctrine.orm.entity_manager"]
tags:
- { name: kernel.event_listener, event: oneup_uploader.post_upload, method: onUpload }
and:
directory: ./uploads/gallery
Now created, uploaded file in "uploads/gallery/..."
But...
CRITICAL - Uncaught PHP Exception
Symfony\Component\Debug\Exception\ContextErrorException: "Catchable
Fatal Error: Argument 1 passed to
Cms\AdminBundle\EventListener\UploadListener::onUpload() must be an
instance of Oneup\UploaderBundle\Event\PostPersistEvent, instance of
Oneup\UploaderBundle\Event\PostUploadEvent given" at
/home/cms/public_html/src/Cms/AdminBundle/EventListener/UploadListener.php
line 17 Context:
{"exception":"Object(Symfony\Component\Debug\Exception\ContextErrorException)"}
Returns blueimp "Internal Server Error ..." and doesn't add records in the Entity.

OneupUploaderBundle: Files are not uploaded and UploadListener not persist to DB, why?

I'm trying to upload one or more files using OneupUploaderBundle but I can not get it to work since files aren't uploaded and nothing is persisted to DB. I'll explain what I've done til now:
config.yml:
oneup_uploader:
mappings:
recaudos:
frontend: blueimp
storage:
service: ~
type: filesystem
filesystem: ~
directory: %kernel.root_dir%/../web/uploads/recaudos
stream_wrapper: ~
sync_buffer_size: 100K
allowed_mimetypes: [application/msword,image/jpeg,image/pjpeg,image/png,application/pdf,application/vnd.oasis.opendocument.text]
#disallowed_mimetypes: []
error_handler: oneup_uploader.error_handler.noop
# Set max_size to -1 for gracefully downgrade this number to the systems max upload size.
#max_size: 9223372036854775807
use_orphanage: true
enable_progress: true
enable_cancelation: true
namer: oneup_uploader.namer.uniqid
At Twig template only this:
<input id="fileUpload3" class="fileUpload" type="file" name="fileUpload3[]" data-url="{{ oneup_uploader_endpoint('recaudos') }}" multiple />
$(document).ready(function(){
$('fileUpload3').fileupload();
});
And latest this is the Listener for onUpload event:
namespace AppBundle\EventListener;
use Oneup\UploaderBundle\Event\PostPersistEvent;
use Symfony\Component\HttpFoundation\Request;
use AppBundle\Entity;
class UploadListener
{
protected $doctrine;
public function __construct($doctrine)
{
$this->doctrine = $doctrine;
}
public function onUpload(PostPersistEvent $event, Request $request)
{
$session = $request->getSession();
$em = $this->doctrine->getManager();
$request = $event->getRequest();
$tempfile = $event->getFile();
$productoSolicitud = $em->getRepository('SolicitudProducto')->find($session->get('productoSolicitudId'));
$recaudosTramiteProductoSolicitud = new Entity\RecaudosTramitesProductoSolicitud();
$recaudosTramiteProductoSolicitud->setProductoSolicitud($productoSolicitud);
$filenamePart = explode("--", $tempfile->getName());
$pathinfo = pathinfo($tempfile->getName());
$recaudosTramiteProductoSolicitud->setArchivo($pathinfo['filename']);
$em->persist($recaudosTramiteProductoSolicitud);
$em->flush();
}
}
And of course I have service defined also:
appbundle.upload_listener:
class: "AppBundle\EventListener\UploadListener"
arguments: [#doctrine]
tags:
- { name: 'kernel.event_listener', event: "oneup_uploader.post_persist", method: "onUpload" }
Did I miss something? Why file are not uploaded and data is not persisted? As you may see in the attached image there is a post request to _uploader/recaudos/upload, any advice?
I just checked my own OneupUploader implementation:
Rename your function "onUpload" to "onPostUpload" and change your service configuration to this:
appbundle.upload_listener:
class: "AppBundle\EventListener\UploadListener"
arguments: [#doctrine]
tags:
- { name: 'kernel.event_listener', event: oneup_uploader.post_upload, method: onPostUpload }
Should work, works for me.
If you need your original file name you also need an onUpload Method and this:
tags:
# - {...
- { name: kernel.event_listener, event: oneup_uploader.pre_upload, method: onUpload }
Regarding your comment:
//UploadListener
class UploadListener
{
protected $originalName;
public function onUpload(PreUploadEvent $event)
{
$file = $event->getFile();
$this->originalName = $file->getClientOriginalName();
}
public function onPostUpload(PostUploadEvent $event)
{
$fileEntity = new YourFileEntity();
$fileEntity->setYourOriginalNameProperty($this->originalName);
//...
}
}

FOS Elastica manual provider service injection issue

I am trying to create a manual provider to manually populate my FOS Elastica index to account for some complex joins. At the moment, I am just trying to get the provider to work even without the joins, and I am having trouble injecting the correct Elastica Type into my constructor for the provider. Here is the constructor of my provider:
// ...
class EmpPosDeptProvider implements ProviderInterface
{
private $em;
protected $type;
public function __construct(Type $type, EntityManager $em)
{
$this->type = $type;
$this->em = $em->getRepository('CcitEmployeesBundle:Position');
}
// ...
and here is my services.yml file:
services:
employees.search_provider.empPosDept:
class: Ccit\EmployeesBundle\Search\EmpPosDeptProvider
tags:
- { name: fos_elastica.provider, index: employees, type: empPosDept }
arguments:
- %fos_elastica.type.class%
- #doctrine.orm.entity_manager
When I try to execute php app/console fos:elastica:populate I am receiving the following error:
PHP Catchable fatal error: Argument 1 passed to Ccit\EmployeesBundle\Search
\EmpPosDeptProvider::__construct() must be an instance of Elastica\Type, string given,
called in /vagrant-nfs/employees/app/cache/dev/appDevDebugProjectContainer.php on line 736
and defined in /vagrant-nfs/employees/src/Ccit/EmployeesBundle/Search
/EmpPosDeptProvider.php on line 23
Does anyone know what I need to give as a correct argument in my services.yml file? Or could the problem be something else entirely?
You're passing a string containing Ccit\EmployeesBundle\Search\EmpPosDeptProvider. You have to pass an instance of EmpPosDeptProvider, and it may be declared in your services.yml something like:
services:
fos_elastica.type:
class: %fos_elastica.type.class%
employees.search_provider.empPosDept:
class: Ccit\EmployeesBundle\Search\EmpPosDeptProvider
tags:
- { name: fos_elastica.provider, index: employees, type: empPosDept }
arguments:
- #fos_elastica.type
- #doctrine.orm.entity_manager
Apparently I needed to provide the explicit path to the type I was referencing. The following line worked:
#fos_elastica.index.employees.employeePositionDepartment
This makes sense given that my config.yml file contains the following:
fos_elastica:
clients:
default: { host: localhost, port: 9200 }
indexes:
employees:
client: default
types:
employeePositionDepartment:
mappings:
id: { type: integer }
title: { type: string }
startDate: { type: date, format: date_time_no_millis }
endDate: { type: date, format: date_time_no_millis }
supervisor: { type: integer }
Thanks to anyone who was considering helping me with this rather elementary question.

In Symfony2, can the validation.yml file be split into multiple files using imports?

Right now, I have a file called validation.yml with the validation of all the bundle's entities in one file.
validation.yml
Blogger\BlogBundle\Entity\Comment
properties:
username:
- NotBlank:
message: You must enter your name
- MaxLength: 50
comment:
- NotBlank:
message: You must enter a comment
- MinLength: 50
Blogger\BlogBundle\Entity\Enquiry:
properties:
name:
- NotBlank: ~
email:
- Email:
message: symblog does not like invalid emails. Give me a real one!
subject:
- NotBlank: ~
- MaxLength: 50
body:
- MinLength: 50
But I'd like to split it into two files and import them both. This is what I tried and it didn't work:
validation.yml
imports:
- { resource: comment.yml }
- { resource: enquiry.yml }
comment.yml
Blogger\BlogBundle\Entity\Comment
properties:
username:
- NotBlank:
message: You must enter your name
- MaxLength: 50
comment:
- NotBlank:
message: You must enter a comment
- MinLength: 50
enquiry.yml
Blogger\BlogBundle\Entity\Enquiry:
properties:
name:
- NotBlank: ~
email:
- Email:
message: symblog does not like invalid emails. Give me a real one!
subject:
- NotBlank: ~
- MaxLength: 50
body:
- MinLength: 50
Add these lines in load method of src/Blogger/BlogBundle/DependencyInjection/BloggerBlogExtension.php.
public function load(array $configs, ContainerBuilder $container)
{
//...
$yamlMappingFiles = $container->getParameter('validator.mapping.loader.yaml_files_loader.mapping_files');
$yamlMappingFiles[] = __DIR__.'/../Resources/config/comment.yml';
$yamlMappingFiles[] = __DIR__.'/../Resources/config/enquiry.yml';
$container->setParameter('validator.mapping.loader.yaml_files_loader.mapping_files', $yamlMappingFiles);
}
Answer added at 2015
As of Symfony 2.7, XML and Yaml constraint files located in the
Resources/config/validation sub-directory of a bundle are loaded.
Prior to 2.7, only Resources/config/validation.yml (or .xml) were
loaded.
More info at:
Github PR: [FrameworkBundle] "mappings" for validation #13878
Symfony doc: The Basics of Validation
Symfony 2.5 broke the above solutions. See: https://stackoverflow.com/a/24210501/175753
You can add to your services.xml
<parameters>
<parameter key="validator.mapping.loader.yaml_files_loader.mapping_files" type="collection">
<parameter>Blogger\BlogBundle\Resources\config\comment.yml</parameter>
<parameter>Blogger\BlogBundle\Resources\config\enquiry.yml</parameter>
</parameter>
</parameters>
Another alternative:
public function load(array $configs, ContainerBuilder $container)
{
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$validatorFiles = $container->getParameter('validator.mapping.loader.yaml_files_loader.mapping_files');
$finder = new Finder();
foreach ($finder->files()->in(__DIR__ . '/../Resources/config/validation') as $file) {
$validatorFiles[] = $file->getRealPath();
}
$container->setParameter('validator.mapping.loader.yaml_files_loader.mapping_files', $validatorFiles);
}
This way, using the Finder Component, you don't have to be concerned about touching this file each time you add a new validator file.
Solutions above are not working in Symfony 2.3.
In 2.3 it's easier to load multiple Yml files from loader. For example:
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
$loader->load('services/menu.yml'); //new file to load
Since Symfony 3.3 all files present in YourBundle/Resources/config/validation/* are registered.
Since Symfony 3.4 all files present in %kernel.project_dir%/config/validator/* are also registered.
This is YAML alternative to #MaksSlesarenko answer.
parameters:
validator.mapping.loader.yaml_files_loader.mapping_files:
- "%kernel.root_dir%/../src/CompanyName/TestBundle/Resources/config/validation/Entity.DbObject.yml"
BTW is there any way to change %kernel.root_dir%/../src/CompanyName/TestBundle/ to some bundle root variable (like %kernel.root_dir%)?

Categories