2015-08-18 00:00:26 +00:00
< ? php
/*
* This file is part of the Symfony package .
*
* ( c ) Fabien Potencier < fabien @ symfony . com >
*
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
*/
namespace Symfony\Component\Validator ;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException ;
use Symfony\Component\Validator\Exception\InvalidArgumentException ;
use Symfony\Component\Validator\Exception\InvalidOptionsException ;
use Symfony\Component\Validator\Exception\MissingOptionsException ;
/**
* Contains the properties of a constraint definition .
*
2016-04-20 16:56:34 +00:00
* A constraint can be defined on a class , a property or a getter method .
2015-08-18 00:00:26 +00:00
* The Constraint class encapsulates all the configuration required for
2016-04-20 16:56:34 +00:00
* validating this class , property or getter result successfully .
2015-08-18 00:00:26 +00:00
*
* Constraint instances are immutable and serializable .
*
* @ property array $groups The groups that the constraint belongs to
*
* @ author Bernhard Schussek < bschussek @ gmail . com >
*/
abstract class Constraint
{
/**
* The name of the group given to all constraints with no explicit group .
*/
const DEFAULT_GROUP = 'Default' ;
/**
* Marks a constraint that can be put onto classes .
*/
const CLASS_CONSTRAINT = 'class' ;
/**
* Marks a constraint that can be put onto properties .
*/
const PROPERTY_CONSTRAINT = 'property' ;
/**
2015-10-08 18:40:12 +00:00
* Maps error codes to the names of their constants .
2015-08-18 00:00:26 +00:00
*/
protected static $errorNames = array ();
/**
2015-10-08 18:40:12 +00:00
* Domain - specific data attached to a constraint .
*
2015-08-18 00:00:26 +00:00
* @ var mixed
*/
public $payload ;
/**
* Returns the name of the given error code .
*
2016-04-20 16:56:34 +00:00
* @ param string $errorCode The error code
2015-08-18 00:00:26 +00: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-11-23 12:29:20 +00:00
throw new InvalidArgumentException ( sprintf ( 'The error code "%s" does not exist for constraint of type "%s".' , $errorCode , \get_called_class ()));
2015-08-18 00:00:26 +00:00
}
return static :: $errorNames [ $errorCode ];
}
/**
* Initializes the constraint with options .
*
* 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 .
*
* Alternatively you can override the method getDefaultOption () to return the
* 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
* getRequiredOptions () to return the names of these options . If any
* option is not set here , an exception is thrown .
*
* @ 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
* returned by getRequiredOptions ()
* @ throws ConstraintDefinitionException When you don ' t pass an associative
* array , but getDefaultOption () returns
* null
*/
public function __construct ( $options = null )
{
$invalidOptions = array ();
$missingOptions = array_flip (( array ) $this -> getRequiredOptions ());
$knownOptions = get_object_vars ( $this );
// The "groups" option is added to the object lazily
$knownOptions [ 'groups' ] = true ;
2018-11-23 12:29:20 +00:00
if ( \is_array ( $options ) && \count ( $options ) >= 1 && isset ( $options [ 'value' ]) && ! property_exists ( $this , 'value' )) {
2015-08-18 00:00:26 +00:00
$options [ $this -> getDefaultOption ()] = $options [ 'value' ];
unset ( $options [ 'value' ]);
}
2018-11-23 12:29:20 +00:00
if ( \is_array ( $options )) {
2017-02-03 00:28:38 +00:00
reset ( $options );
}
2018-11-23 12:29:20 +00:00
if ( \is_array ( $options ) && \count ( $options ) > 0 && \is_string ( key ( $options ))) {
2015-08-18 00:00:26 +00:00
foreach ( $options as $option => $value ) {
if ( array_key_exists ( $option , $knownOptions )) {
$this -> $option = $value ;
unset ( $missingOptions [ $option ]);
} else {
$invalidOptions [] = $option ;
}
}
2018-11-23 12:29:20 +00:00
} elseif ( null !== $options && ! ( \is_array ( $options ) && 0 === \count ( $options ))) {
2015-08-18 00:00:26 +00:00
$option = $this -> getDefaultOption ();
if ( null === $option ) {
2018-11-23 12:29:20 +00:00
throw new ConstraintDefinitionException ( sprintf ( 'No default option is configured for constraint %s' , \get_class ( $this )));
2015-08-18 00:00:26 +00:00
}
if ( array_key_exists ( $option , $knownOptions )) {
$this -> $option = $options ;
unset ( $missingOptions [ $option ]);
} else {
$invalidOptions [] = $option ;
}
}
2018-11-23 12:29:20 +00:00
if ( \count ( $invalidOptions ) > 0 ) {
throw new InvalidOptionsException ( sprintf ( 'The options "%s" do not exist in constraint %s' , implode ( '", "' , $invalidOptions ), \get_class ( $this )), $invalidOptions );
2015-08-18 00:00:26 +00:00
}
2018-11-23 12:29:20 +00:00
if ( \count ( $missingOptions ) > 0 ) {
throw new MissingOptionsException ( sprintf ( 'The options "%s" must be set for constraint %s' , implode ( '", "' , array_keys ( $missingOptions )), \get_class ( $this )), array_keys ( $missingOptions ));
2015-08-18 00:00:26 +00: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
*/
public function __set ( $option , $value )
{
if ( 'groups' === $option ) {
$this -> groups = ( array ) $value ;
return ;
}
2018-11-23 12:29:20 +00:00
throw new InvalidOptionsException ( sprintf ( 'The option "%s" does not exist in constraint %s' , $option , \get_class ( $this )), array ( $option ));
2015-08-18 00:00:26 +00: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
*
2018-11-23 12:29:20 +00:00
* @ internal this method should not be used or overwritten in userland code
2015-08-18 00:00:26 +00:00
*/
public function __get ( $option )
{
if ( 'groups' === $option ) {
$this -> groups = array ( self :: DEFAULT_GROUP );
return $this -> groups ;
}
2018-11-23 12:29:20 +00:00
throw new InvalidOptionsException ( sprintf ( 'The option "%s" does not exist in constraint %s' , $option , \get_class ( $this )), array ( $option ));
}
/**
* @ param string $option The option name
*
* @ return bool
*/
public function __isset ( $option )
{
return 'groups' === $option ;
2015-08-18 00:00:26 +00:00
}
/**
* Adds the given group if this constraint is in the Default group .
*
* @ param string $group
*/
public function addImplicitGroupName ( $group )
{
2018-11-23 12:29:20 +00:00
if ( \in_array ( self :: DEFAULT_GROUP , $this -> groups ) && ! \in_array ( $group , $this -> groups )) {
2015-08-18 00:00:26 +00:00
$this -> groups [] = $group ;
}
}
/**
* Returns the name of the default option .
*
* Override this method to define a default option .
*
* @ return string
*
* @ see __construct ()
*/
public function getDefaultOption ()
{
}
/**
* Returns the name of the required options .
*
* Override this method if you want to define required options .
*
* @ return array
*
* @ see __construct ()
*/
public function getRequiredOptions ()
{
return array ();
}
/**
* Returns the name of the class that validates this constraint .
*
* By default , this is the fully qualified name of the constraint class
* suffixed with " Validator " . You can override this method to change that
* behaviour .
*
* @ return string
*/
public function validatedBy ()
{
2018-11-23 12:29:20 +00:00
return \get_class ( $this ) . 'Validator' ;
2015-08-18 00:00:26 +00:00
}
/**
* Returns whether the constraint can be put onto classes , properties or
* both .
*
* This method should return one or more of the constants
* Constraint :: CLASS_CONSTRAINT and Constraint :: PROPERTY_CONSTRAINT .
*
* @ return string | array One or more constant values
*/
public function getTargets ()
{
return self :: PROPERTY_CONSTRAINT ;
}
/**
* Optimizes the serialized value to minimize storage space .
*
* @ return array The properties to serialize
*
* @ internal This method may be replaced by an implementation of
* { @ link \Serializable } in the future . Please don ' t use or
* overwrite it .
*/
public function __sleep ()
{
// Initialize "groups" option if it is not set
$this -> groups ;
return array_keys ( get_object_vars ( $this ));
}
}