简体   繁体   中英

Sonata media validation at admin

I'm trying to validate image. I saw answer at Sonata Media: The file could not be found

How to validate image (width and height). I need help on that. There is no proper doc in net.

To validate image dimensions using sonata media you need to override sonata media's ImageProvider class, sonata uses this class to handle image manipulation.If you already have an extended bundle of sonata media bundle then in services.yml file you can define your own provider as below ,make sure your yml file is included in main config.yml

parameters:
    sonata.media.provider.file.class: Application\Sonata\MediaBundle\Provider\ImageProvider

Now create your provider and extend it with sonata media's ImageProvider overrider validate() function and define your own validation or can override buildCreateForm()/buildEditForm() and define your asserts for binaryContent field

namespace Application\\Sonata\\MediaBundle\\Provider;

//... other uses classes
use Sonata\MediaBundle\Provider\ImageProvider as BaseProvider;

class ImageProvider extends BaseProvider
{

    public function __construct($name, Filesystem $filesystem, CDNInterface $cdn, GeneratorInterface $pathGenerator, ThumbnailInterface $thumbnail, array $allowedExtensions = array(), array $allowedMimeTypes = array(), MetadataBuilderInterface $metadata = null)
    {
        parent::__construct($name, $filesystem, $cdn, $pathGenerator, $thumbnail);

        $this->allowedExtensions = $allowedExtensions;
        $this->allowedMimeTypes = $allowedMimeTypes;
        $this->metadata = $metadata;
    }

    /**
     * {@inheritdoc}
     */
    public function validate(ErrorElement $errorElement, MediaInterface $media)
    {
        if (!$media->getBinaryContent() instanceof \SplFileInfo) {
            return;
        }

        if ($media->getBinaryContent() instanceof UploadedFile) {
            $fileName = $media->getBinaryContent()->getClientOriginalName();
        } elseif ($media->getBinaryContent() instanceof File) {
            $fileName = $media->getBinaryContent()->getFilename();
        } else {
            throw new \RuntimeException(sprintf('Invalid binary content type: %s', get_class($media->getBinaryContent())));
        }

        if (!in_array(strtolower(pathinfo($fileName, PATHINFO_EXTENSION)), $this->allowedExtensions)) {
            $errorElement
                ->with('binaryContent')
                ->addViolation('Invalid extensions')
                ->end();
        }

        if (!in_array($media->getBinaryContent()->getMimeType(), $this->allowedMimeTypes)) {
            $errorElement
                ->with('binaryContent')
                ->addViolation('Invalid mime type : ' . $media->getBinaryContent()->getMimeType())
                ->end();
        }

        if ($media->getWidth() > '1280' || $media->getHeight() > 1280) {
            $errorElement
                ->with('binaryContent')
                ->addViolation('Invalid File Dimension : Please upload 1280px * (1280px) image')
                ->end();
        }
    }

}
 * @Assert\Image(
 *     minWidth = 200,
 *     maxWidth = 400,
 *     minHeight = 200,
 *     maxHeight = 400
 * )

You can add Assert annotation for Entity. Look at : http://symfony.com/doc/current/reference/constraints/Image.html

This code works for me. Only when using SonataMedia in MyBundle(Here AppBundle). I used the same code in SonataUserBundle(Application\\Sonata\\UserBundle\\Entity). But it failed.

Entity:

<?php
// To reduce code i deleted many lines
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Gedmo\Mapping\Annotation as Gedmo;

/**

 * FZHomeSlider
 *
 * @ORM\Table(name="fz__home_slider")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\FZHomeSliderRepository")
 * @ORM\HasLifecycleCallbacks()
 * @Assert\Callback(methods={ "isMediaSizeValid" })
 */
class FZHomeSlider {

    const FILE_PATH = 'image';
    const FILE_SIZE = 200; # kb
    const FILE_MIN_WIDTH = 1024;
    const FILE_MAX_WIDTH = 1024;
    const FILE_MIN_HEIGHT = 250;
    const FILE_MAX_HEIGHT = 250;

    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\OneToOne(targetEntity="Application\Sonata\MediaBundle\Entity\Media" )
     * @ORM\JoinColumns( { @ORM\JoinColumn( referencedColumnName="id", onDelete="CASCADE" ) } )
     * @Assert\NotNull()
     */
    private $image;


    /**
     * Set image
     *
     * @param \Application\Sonata\MediaBundle\Entity\Media $image
     *
     * @return FZHomeSlider
     */
    public function setImage(\Application\Sonata\MediaBundle\Entity\Media $image = null) {
        $this->image = $image;

        return $this;
    }

    /**
     * Get image
     *
     * @return \Application\Sonata\MediaBundle\Entity\Media
     */
    public function getImage() {
        return $this->image;
    }

    /**
     * @param ExecutionContextInterface $context Description
     */
    public function isMediaSizeValid(ExecutionContextInterface $context) {
        $this->fzValidateImage($context, $this->getImage());
    }

    private function fzValidateImage($context, $f) {
        if ($f == NULL) {
            $context->buildViolation('Please select an image.')->atPath(self::FILE_PATH)->addViolation();
        } else if ($f->getSize() > (self::FILE_SIZE * 1024)) {
            $context->buildViolation('The file is too large ( %a% kb). Allowed maximum size is %b% kb.')->atPath(self::FILE_PATH)->setParameters(['%a%' => intval($f->getSize() / 1024), '%b%' => self::FILE_SIZE])->addViolation();
        } else if ($f->getWidth() < self::FILE_MIN_WIDTH) {
            $context->buildViolation('The image width is too small ( %a% px). Minimum width expected is  %b% px.')->atPath(self::FILE_PATH)->setParameters(['%a%' => $f->getWidth(), '%b%' => self::FILE_MIN_WIDTH])->addViolation();
        } else if ($f->getWidth() > self::FILE_MAX_WIDTH) {
            $context->buildViolation('The image width is too big ( %a% px). Allowed maximum width is  %b% px.')->atPath(self::FILE_PATH)->setParameters(['%a%' => $f->getWidth(), '%b%' => self::FILE_MAX_WIDTH])->addViolation();
        } else if ($f->getHeight() < self::FILE_MIN_HEIGHT) {
            $context->buildViolation('The image height is too small ( %a% px). Minimum height expected is  %b% px.')->atPath(self::FILE_PATH)->setParameters(['%a%' => $f->getHeight(), '%b%' => self::FILE_MIN_HEIGHT])->addViolation();
        } else if ($f->getHeight() > self::FILE_MAX_HEIGHT) {
            $context->buildViolation('The image height is too big ( %a% px). Allowed maximum height is  %b% px.')->atPath(self::FILE_PATH)->setParameters(['%a%' => $f->getHeight(), '%b%' => self::FILE_MAX_HEIGHT])->addViolation();
        }
    }

}

In admin :

$formMapper
    ->with('Media')
    ->add('image', 'sonata_type_model_list', ['btn_delete' => false, 'help' => self::$FORM_IMG_HELP, 'required' => false], ['link_parameters' => ['provider' => 'sonata.media.provider.image', 'context' => 'home_slider']])->end()

FINALLY SOLVED & SOLUTIONS:

As per Sonata Admin Doc

UserAdmin

public function getFormBuilder() {
    $this->formOptions['data_class'] = $this->getClass();

    $options = $this->formOptions;
    $options['validation_groups'] = "";

    $formBuilder = $this->getFormContractor()->getFormBuilder($this->getUniqid(), $options);

    $this->defineFormBuilder($formBuilder);

    return $formBuilder;
}
public function validate(ErrorElement $errorElement, $object) {
    // throw new \Exception("bingo");
    $errorElement
            ->with('phone')
            ->assertLength(['min' => 10, 'max' => '14', 'minMessage' => "Phone number must be at least {{ limit }} characters long", 'maxMessage' => "Phone number cannot be longer than {{ limit }} characters"])
            ->end()
    ;
}

Here validation phone is only for reference. You can also validate using validation.yml file.

Application/Sonata/UserBundle/Resources/config/validation.yml

Application\Sonata\UserBundle\Entity\User:
properties:
    phone:
        - Length:
            min:        10
            minMessage: "Phone number must be at least {{ limit }} characters long"
            max:        13
            maxMessage: "Phone number cannot be longer than {{ limit }} characters"
        - Regex:
            pattern:    "/^[\d]{10,13}$/"
    biography:
        - Length:
            min:        5
            minMessage: "Biography must be at least {{ limit }} characters long"
            max:        7
            maxMessage: "Biography cannot be longer than {{ limit }} characters"
#        image:
#            - Image validation is done in Entity

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM