Question

I'm trying hard to find out a way to validate sonata media type form filed. My entity is related to media table with one-to-one relation . Here is relation

 oneToOne:
  user:
    targetEntity: Sinepulse\UserBundle\Entity\User
    mappedBy: profile_info
    cascade: [all]
  profile_image:
    targetEntity: Sinepulse\Sonata\MediaBundle\Entity\Media
    cascade:      [ all ]
    joinColumn:
        name: profile_image_id
        referencedColumnName: id
        nullable: true
        onDelete: 'SET NULL'

My Form here:

                ->add('profile_image', 'sonata_media_type', array(
                'provider' => 'sonata.media.provider.image',
                'context' => 'user',
                'required'=>false,
                'validation_groups' => 'Default'
            ))

My attempted validation:

    profile_image:
    - File: { mimeTypes: [ image/png ], groups: [image,logo, offer] } 

I am help less last few day for finding the solution. Because If I submit other than image file. It threw two exception RuntimeException & InvalidArgumentException. So please help me!

Was it helpful?

Solution

In your validation.yml file you created a rule only for: image, logo and offer groups. But in your form you specify the validation_groups to Default; so if you want to apply that rule, you need to:

Add the group to the form:

->add('profile_image', 'sonata_media_type', array(
    // ...
    'validation_groups' => array('Default', 'image') // or logo or offer
))

Or remove the groups of the validation.yml:

- File: { mimeTypes: [ image/png ] }

OTHER TIPS

I guess, it may be the case to create another provider and specify certain validation process. I'll try to explain my vision with png images provider (Symfony 4 compatible).

First, create provider. It is just the extension of some existing provider from the box (ImageProvider in the case):

namespace App\Provider;

use Sonata\MediaBundle\Provider\ImageProvider;

class PngProvider extends ImageProvider
{
}

Second, define DI configuration in services.yaml:

sonata.media.provider.png:
    class: App\Provider\PngProvider
    tags:
        - { name: sonata.media.provider }
    arguments:
        - 'sonata.media.provider.png'
        - '@sonata.media.filesystem.local'
        - '@sonata.media.cdn.server'
        - '@sonata.media.generator.default'
        - '@sonata.media.thumbnail.format'
        - ['png']
        - ['image/png', 'image/x-png']
    calls:
      - [ setTemplates, [{"helper_view":"SonataMediaBundle:Provider:view_image.html.twig","helper_thumbnail":"SonataMediaBundle:Provider:thumbnail.html.twig"}]]

As you can see, two last arguments define file extensions and mime types for files to upload.

Then, add property for your entity file:

namespace App\Entity;

use App\Entity\Media; // or you Media class
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;

class SomeEntity
{
    /**
     * @var Media
     * @Assert\Valid
     * @ORM\ManyToOne(targetEntity="Media", cascade={"all"})
     */
    private $pngFileProperty;

Please, pay attention to @Assert\Valid constraint for the media property, or media file would skip validation during uploading.

Now you can use your provider with some sonata media contexts:

sonata_media:
    contexts:
        some_context:
            providers:
                - sonata.media.provider.png
            formats: ~

And use it, for example, in form types:

use Sonata\MediaBundle\Form\Type\MediaType;
...
$builder->add('pngFileProperty', MediaType::class, [
    'context'  => 'some_context',
    'provider' => 'sonata.media.provider.png',
])

You can provide some additional validation conditions (max file size or smth like this stuff) by overriding PngProvider::validate() method for your custom provider:

namespace App\Provider;

use Sonata\CoreBundle\Validator\ErrorElement;
use Sonata\MediaBundle\Model\MediaInterface;
use Sonata\MediaBundle\Provider\ImageProvider;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;

class PngProvider extends ImageProvider
{   
    const VERY_BIG_FILE = 100000; // bytes

    public function validate(ErrorElement $errorElement, MediaInterface $media)
    {
        parent::validate($errorElement, $media);

        if ($media->getBinaryContent() instanceof UploadedFile) {
            $size = $media->getBinaryContent()->getClientSize();
        } elseif ($media->getBinaryContent() instanceof File) {
            $size = $media->getBinaryContent()->getSize();
        } else {
            // parent would throw an Exception in this case so be happy, don't worry
        }

        if ($size > self::VERY_BIG_FILE) {
            $errorElement
                ->with('binaryContent')
                    ->addViolation('The file is too big, max size: '.self::VERY_BIG_FILE)
                ->end();
        }
    }
}

There are multiple ways to do this

From an Entity:

/**  
* @Assert\NotBlank() 
* @Assert\File(
*     maxSize = "5m",
*     mimeTypes = {"application/pdf", "application/x-pdf", "application/msword"},
* )  
* @ORM\ManyToOne(targetEntity="Application\Sonata\MediaBundle\Entity\Media", cascade={"remove", "persist"}, fetch="LAZY")  */ 
protected $cv;

/**  
* @Assert\NotBlank()  
* @Assert\File(
*     maxSize = "5m",
*     mimeTypes = {"application/pdf", "application/x-pdf", "application/msword"},
* )  
* @ORM\ManyToOne(targetEntity="Application\Sonata\MediaBundle\Entity\Media", cascade={"remove", "persist"}, fetch="LAZY")  */ 
protected $letter;

Alternatively, From an Admin class

<?php # Sapiens\Bundle\JobBundle\Form\Type\JobApplyType

public function validate(ErrorElement $errorElement, JobApply $jobApply)
{
    $errorElement
        ->with('cv.binaryContent')
            ->assertNotNull(array())
            ->assertNotBlank()
            ->assertFile(array('maxSize' => '3000000', 'mimeTypes' => array("application/pdf", "application/x-pdf", "application/msword")))
        ->end()
        ->with('letter.binaryContent')
            ->assertNotNull(array())
            ->assertNotBlank()
            ->assertFile(array('maxSize' => '3000000', 'mimeTypes' => array("application/pdf", "application/x-pdf", "application/msword")))
        ->end();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top