2010-06-24 09:40:05 +01:00
< ? php
2010-10-02 11:42:31 +01:00
/*
2011-01-15 13:29:43 +00:00
* This file is part of the Symfony package .
2010-10-02 11:42:31 +01:00
*
2011-03-06 11:40:06 +00:00
* ( c ) Fabien Potencier < fabien @ symfony . com >
2010-10-02 11:42:31 +01:00
*
2011-01-15 13:29:43 +00:00
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
2010-10-02 11:42:31 +01:00
*/
2011-01-15 13:29:43 +00:00
namespace Symfony\Component\Validator ;
2014-03-17 15:44:19 +00:00
use Symfony\Component\Validator\Exception\ConstraintDefinitionException ;
2014-09-24 11:08:18 +01:00
use Symfony\Component\Validator\Exception\InvalidArgumentException ;
2010-08-20 22:09:55 +01:00
use Symfony\Component\Validator\Exception\InvalidOptionsException ;
use Symfony\Component\Validator\Exception\MissingOptionsException ;
2010-06-24 09:40:05 +01:00
/**
* Contains the properties of a constraint definition .
*
2016-03-18 20:39:03 +00:00
* A constraint can be defined on a class , a property or a getter method .
2010-06-24 09:40:05 +01:00
* The Constraint class encapsulates all the configuration required for
2016-03-18 20:39:03 +00:00
* validating this class , property or getter result successfully .
2010-06-24 09:40:05 +01:00
*
* Constraint instances are immutable and serializable .
*
2014-07-29 11:16:36 +01:00
* @ property array $groups The groups that the constraint belongs to
*
2012-05-26 08:48:33 +01:00
* @ author Bernhard Schussek < bschussek @ gmail . com >
2010-06-24 09:40:05 +01:00
*/
2010-11-16 21:08:53 +00:00
abstract class Constraint
2010-06-24 09:40:05 +01:00
{
2011-01-19 14:30:43 +00:00
/**
2014-12-21 17:00:50 +00:00
* The name of the group given to all constraints with no explicit group .
2011-01-19 14:30:43 +00:00
*/
2010-06-24 10:24:08 +01:00
const DEFAULT_GROUP = 'Default' ;
2011-01-19 14:30:43 +00:00
/**
2014-12-21 17:00:50 +00:00
* Marks a constraint that can be put onto classes .
2011-01-19 14:30:43 +00:00
*/
const CLASS_CONSTRAINT = 'class' ;
/**
2014-12-21 17:00:50 +00:00
* Marks a constraint that can be put onto properties .
2011-01-19 14:30:43 +00:00
*/
const PROPERTY_CONSTRAINT = 'property' ;
2014-09-24 11:08:18 +01:00
/**
2015-08-24 07:53:33 +01:00
* Maps error codes to the names of their constants .
2014-09-24 11:08:18 +01:00
*/
2019-01-16 09:39:14 +00:00
protected static $errorNames = [];
2014-09-24 11:08:18 +01:00
2014-09-23 16:29:30 +01:00
/**
2015-08-24 07:53:33 +01:00
* Domain - specific data attached to a constraint .
*
2014-09-23 16:29:30 +01:00
* @ var mixed
*/
public $payload ;
2014-09-24 11:08:18 +01:00
/**
* Returns the name of the given error code .
*
2016-03-12 00:32:06 +00:00
* @ param string $errorCode The error code
2014-09-24 11:08:18 +01:00
*
* @ return string The name of the error code
*
* @ throws InvalidArgumentException If the error code does not exist
*/
public static function getErrorName ( $errorCode )
{
if ( ! isset ( static :: $errorNames [ $errorCode ])) {
2018-09-08 13:44:02 +01:00
throw new InvalidArgumentException ( sprintf ( 'The error code "%s" does not exist for constraint of type "%s".' , $errorCode , \get_called_class ()));
2014-09-24 11:08:18 +01:00
}
return static :: $errorNames [ $errorCode ];
}
2010-06-24 10:24:08 +01:00
/**
2010-10-15 22:49:09 +01:00
* Initializes the constraint with options .
2010-06-24 10:24:08 +01:00
*
* You should pass an associative array . The keys should be the names of
* existing properties in this class . The values should be the value for these
* properties .
*
2011-03-30 22:18:15 +01:00
* Alternatively you can override the method getDefaultOption () to return the
2010-06-24 10:24:08 +01:00
* name of an existing property . If no associative array is passed , this
* property is set instead .
*
* You can force that certain options are set by overriding
2011-03-30 22:18:15 +01:00
* getRequiredOptions () to return the names of these options . If any
2010-06-24 10:24:08 +01:00
* option is not set here , an exception is thrown .
*
2010-10-15 22:49:09 +01:00
* @ param mixed $options The options ( as associative array )
* or the value for the default
* option ( any other type )
*
* @ throws InvalidOptionsException When you pass the names of non - existing
* options
* @ throws MissingOptionsException When you don ' t pass any of the options
2011-03-30 22:18:15 +01:00
* returned by getRequiredOptions ()
2010-10-15 22:49:09 +01:00
* @ throws ConstraintDefinitionException When you don ' t pass an associative
2011-03-30 22:18:15 +01:00
* array , but getDefaultOption () returns
2014-01-07 03:21:50 +00:00
* null
2010-06-24 10:24:08 +01:00
*/
public function __construct ( $options = null )
2010-06-24 09:40:05 +01:00
{
2019-03-28 00:28:16 +00:00
$defaultOption = $this -> getDefaultOption ();
2019-01-16 09:39:14 +00:00
$invalidOptions = [];
2011-03-31 13:02:00 +01:00
$missingOptions = array_flip (( array ) $this -> getRequiredOptions ());
2014-07-29 11:16:36 +01:00
$knownOptions = get_object_vars ( $this );
// The "groups" option is added to the object lazily
$knownOptions [ 'groups' ] = true ;
2010-06-24 09:40:05 +01:00
2019-03-28 00:28:16 +00:00
if ( \is_array ( $options ) && isset ( $options [ 'value' ]) && ! property_exists ( $this , 'value' )) {
if ( null === $defaultOption ) {
throw new ConstraintDefinitionException ( sprintf ( 'No default option is configured for constraint "%s".' , \get_class ( $this )));
}
$options [ $defaultOption ] = $options [ 'value' ];
2013-09-10 16:23:32 +01:00
unset ( $options [ 'value' ]);
2010-06-24 10:24:08 +01:00
}
2018-07-05 12:24:53 +01:00
if ( \is_array ( $options )) {
2016-10-01 22:18:01 +01:00
reset ( $options );
}
2018-11-15 16:40:37 +00:00
if ( $options && \is_array ( $options ) && \is_string ( key ( $options ))) {
2010-06-24 10:24:08 +01:00
foreach ( $options as $option => $value ) {
2019-02-23 15:06:07 +00:00
if ( \array_key_exists ( $option , $knownOptions )) {
2010-06-24 10:24:08 +01:00
$this -> $option = $value ;
unset ( $missingOptions [ $option ]);
} else {
$invalidOptions [] = $option ;
}
}
2018-07-05 12:24:53 +01:00
} elseif ( null !== $options && ! ( \is_array ( $options ) && 0 === \count ( $options ))) {
2019-03-28 00:28:16 +00:00
if ( null === $defaultOption ) {
throw new ConstraintDefinitionException ( sprintf ( 'No default option is configured for constraint "%s".' , \get_class ( $this )));
2010-06-24 10:24:08 +01:00
}
2019-03-28 00:28:16 +00:00
if ( \array_key_exists ( $defaultOption , $knownOptions )) {
$this -> $defaultOption = $options ;
unset ( $missingOptions [ $defaultOption ]);
2010-06-24 10:24:08 +01:00
} else {
2019-03-28 00:28:16 +00:00
$invalidOptions [] = $defaultOption ;
2010-06-24 10:24:08 +01:00
}
2010-06-24 09:40:05 +01:00
}
2010-06-24 10:24:08 +01:00
2018-07-05 12:24:53 +01:00
if ( \count ( $invalidOptions ) > 0 ) {
2019-03-28 00:28:16 +00:00
throw new InvalidOptionsException ( sprintf ( 'The options "%s" do not exist in constraint "%s".' , implode ( '", "' , $invalidOptions ), \get_class ( $this )), $invalidOptions );
2010-06-24 10:24:08 +01:00
}
2018-07-05 12:24:53 +01:00
if ( \count ( $missingOptions ) > 0 ) {
2019-03-28 00:28:16 +00:00
throw new MissingOptionsException ( sprintf ( 'The options "%s" must be set for constraint "%s".' , implode ( '", "' , array_keys ( $missingOptions )), \get_class ( $this )), array_keys ( $missingOptions ));
2010-06-24 09:40:05 +01:00
}
2010-06-24 10:24:08 +01:00
}
/**
2014-07-29 11:16:36 +01:00
* Sets the value of a lazily initialized option .
*
* Corresponding properties are added to the object on first access . Hence
* this method will be called at most once per constraint instance and
* option name .
*
* @ param string $option The option name
* @ param mixed $value The value to set
*
* @ throws InvalidOptionsException If an invalid option name is given
2010-06-24 10:24:08 +01:00
*/
public function __set ( $option , $value )
{
2014-07-29 11:16:36 +01:00
if ( 'groups' === $option ) {
$this -> groups = ( array ) $value ;
return ;
}
2019-03-28 00:28:16 +00:00
throw new InvalidOptionsException ( sprintf ( 'The option "%s" does not exist in constraint "%s".' , $option , \get_class ( $this )), [ $option ]);
2014-07-29 11:16:36 +01:00
}
/**
* Returns the value of a lazily initialized option .
*
* Corresponding properties are added to the object on first access . Hence
* this method will be called at most once per constraint instance and
* option name .
*
* @ param string $option The option name
*
* @ return mixed The value of the option
*
* @ throws InvalidOptionsException If an invalid option name is given
*
2017-09-11 10:28:55 +01:00
* @ internal this method should not be used or overwritten in userland code
2014-07-29 11:16:36 +01:00
*/
public function __get ( $option )
{
if ( 'groups' === $option ) {
2019-01-16 09:39:14 +00:00
$this -> groups = [ self :: DEFAULT_GROUP ];
2014-07-29 11:16:36 +01:00
return $this -> groups ;
}
2019-03-28 00:28:16 +00:00
throw new InvalidOptionsException ( sprintf ( 'The option "%s" does not exist in constraint "%s".' , $option , \get_class ( $this )), [ $option ]);
2010-06-24 09:40:05 +01:00
}
2010-06-24 10:24:08 +01:00
2018-01-19 11:39:28 +00:00
/**
* @ param string $option The option name
*
* @ return bool
*/
public function __isset ( $option )
{
return 'groups' === $option ;
}
2010-06-24 10:24:08 +01:00
/**
2014-12-21 17:00:50 +00:00
* Adds the given group if this constraint is in the Default group .
2010-06-24 10:24:08 +01:00
*
* @ param string $group
*/
public function addImplicitGroupName ( $group )
2010-06-24 09:40:05 +01:00
{
2018-07-05 12:24:53 +01:00
if ( \in_array ( self :: DEFAULT_GROUP , $this -> groups ) && ! \in_array ( $group , $this -> groups )) {
2010-06-24 10:24:08 +01:00
$this -> groups [] = $group ;
}
2010-06-24 09:40:05 +01:00
}
2010-06-24 10:24:08 +01:00
/**
2014-12-21 17:00:50 +00:00
* Returns the name of the default option .
2010-06-24 10:24:08 +01:00
*
* Override this method to define a default option .
*
2019-04-05 10:10:41 +01:00
* @ return string | null
2014-12-21 17:00:50 +00:00
*
2010-06-24 10:24:08 +01:00
* @ see __construct ()
*/
2011-03-30 22:18:15 +01:00
public function getDefaultOption ()
2010-06-24 09:40:05 +01:00
{
2019-04-05 10:10:41 +01:00
return null ;
2010-06-24 09:40:05 +01:00
}
2010-06-24 10:24:08 +01:00
/**
2014-12-21 17:00:50 +00:00
* Returns the name of the required options .
2010-06-24 10:24:08 +01:00
*
* Override this method if you want to define required options .
*
* @ return array
2014-12-21 17:00:50 +00:00
*
2010-06-24 10:24:08 +01:00
* @ see __construct ()
*/
2011-03-30 22:18:15 +01:00
public function getRequiredOptions ()
2010-06-24 09:40:05 +01:00
{
2019-01-16 09:39:14 +00:00
return [];
2010-06-24 09:40:05 +01:00
}
2010-06-24 10:24:08 +01:00
/**
2014-12-21 17:00:50 +00:00
* Returns the name of the class that validates this constraint .
2010-06-24 10:24:08 +01:00
*
* By default , this is the fully qualified name of the constraint class
* suffixed with " Validator " . You can override this method to change that
2019-03-25 07:48:46 +00:00
* behavior .
2010-06-24 10:24:08 +01:00
*
* @ return string
*/
public function validatedBy ()
2010-06-24 09:40:05 +01:00
{
2018-07-05 12:24:53 +01:00
return \get_class ( $this ) . 'Validator' ;
2010-06-24 09:40:05 +01:00
}
2011-01-19 14:30:43 +00:00
/**
* Returns whether the constraint can be put onto classes , properties or
2014-12-21 17:00:50 +00:00
* both .
2011-01-19 14:30:43 +00:00
*
* This method should return one or more of the constants
* Constraint :: CLASS_CONSTRAINT and Constraint :: PROPERTY_CONSTRAINT .
*
2014-11-30 13:33:44 +00:00
* @ return string | array One or more constant values
2011-01-19 14:30:43 +00:00
*/
2011-05-25 09:51:35 +01:00
public function getTargets ()
{
return self :: PROPERTY_CONSTRAINT ;
}
2014-07-29 11:16:36 +01:00
/**
* Optimizes the serialized value to minimize storage space .
*
2019-01-30 09:03:33 +00:00
* @ internal
2014-07-29 11:16:36 +01:00
*/
2019-08-20 12:52:38 +01:00
public function __sleep () : array
2014-07-29 11:16:36 +01:00
{
// Initialize "groups" option if it is not set
2014-08-18 12:50:08 +01:00
$this -> groups ;
2014-07-29 11:16:36 +01:00
return array_keys ( get_object_vars ( $this ));
}
2011-06-08 11:16:48 +01:00
}