问题
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.
回答1:
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();
}
}
}
回答2:
* @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
回答3:
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
来源:https://stackoverflow.com/questions/35691255/sonata-media-validation-at-admin