Showing posts with label constaint. Show all posts
Showing posts with label constaint. Show all posts

Friday, January 8, 2016

Symfony custom constaint: check total size of several form attachements


The cookbook link on how to create a custom constraint is this one:
http://symfony.com/doc/master/cookbook/validation/custom_constraint.html


Request: total size of form attachments should not be bigger than a given value.

Implementation:

I've created a directory 'Validator' under my Bundle where I added two classes:
- FilesTotalSize which extends class Constaint
- FilesTotalSizeValidator extends ConstaintValidator

FilesTotalSize:


<?php
namespace Bundle\Validator;

use Symfony\Component\Validator\Constraint;

/** @Annotation */
class FilesTotalSize extends Constraint
{
    public $message;
   
    public function validatedBy()
    {
        return get_class($this).'Validator';
    }

    public function getTargets()
    {
        return self::CLASS_CONSTRAINT;
    }
}


The name of the Validation class will be constraint class concatenated with 'Validator';

Because this constraint is checking values from several fields is considered a class validation (as opposite to field validation which can be seen in the documentation examples ).
For this reason getTargets will return CLASS_CONSTRAINT.

The actual check of the condition is made in the validator class. The variable '$value' will give access to the object to be validated. 'attachement1', 'attachement2' and 'attachement3' are the names of the fields declared in the Entity used for file uploading (file). The size is expressed in bytes, so for 3MB I have 3 millions of bytes. The method  'addViolation' receive as parameter the error message to be displayed.
.
FilesTotalSizeValidator:

<?php
namespace  Bundle\Validator;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;


class FilesTotalSizeValidator extends ConstraintValidator
{
    public function validate($value, Constraint $constraint)
    {
        $size_att1=0;
        $size_att2=0;
        $size_att3=0;
       
        if (property_exists($value, 'attachement1')){
            if(!is_null($value->getAttachement1())){
                $size_att1= $value->getAttachement1()->getClientSize();
            }
        }
       
        if (property_exists($value, 'attachement2')){
            if(!is_null($value->getAttachement2())){
                $size_att2= $value->getAttachement2()->getClientSize();
            }
        }
       
        if (property_exists($value, 'attachement3')){
            if(!is_null($value->getAttachement3())){
                $size_att3= $value->getAttachement3()->getClientSize();
            }
        }
       
        $totalSize=0;
        $totalSize=(int)$size_att1 +(int)$size_att2 +(int)$size_att3;

        if ($totalSize > 3145728) {  //check if total size of files is bigger than 3MB
            $this->context->addViolation('Maximum size is 3MB!');
        }
    }
}



Usage:

In the entity class:

use MyBundle\Validator\FilesTotalSize;

/**
 * @ORM\Entity
 * @FilesTotalSize
 */


class EntityName {