Update to drupal 8.0.0-rc1. For more information, see https://www.drupal.org/node/2582663

This commit is contained in:
Greg Anderson 2015-10-08 11:40:12 -07:00
parent eb34d130a8
commit f32e58e4b1
8476 changed files with 211648 additions and 170042 deletions

View file

@ -0,0 +1,49 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
/**
* Used for the comparison of values.
*
* @author Daniel Holmes <daniel@danielholmes.org>
*/
abstract class AbstractComparison extends Constraint
{
public $message;
public $value;
/**
* {@inheritdoc}
*/
public function __construct($options = null)
{
if (is_array($options) && !isset($options['value'])) {
throw new ConstraintDefinitionException(sprintf(
'The %s constraint requires the "value" option to be set.',
get_class($this)
));
}
parent::__construct($options);
}
/**
* {@inheritdoc}
*/
public function getDefaultOption()
{
return 'value';
}
}

View file

@ -0,0 +1,83 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* Provides a base class for the validation of property comparisons.
*
* @author Daniel Holmes <daniel@danielholmes.org>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
abstract class AbstractComparisonValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof AbstractComparison) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\AbstractComparison');
}
if (null === $value) {
return;
}
$comparedValue = $constraint->value;
// Convert strings to DateTimes if comparing another DateTime
// This allows to compare with any date/time value supported by
// the DateTime constructor:
// http://php.net/manual/en/datetime.formats.php
if (is_string($comparedValue)) {
if ($value instanceof \DatetimeImmutable) {
// If $value is immutable, convert the compared value to a
// DateTimeImmutable too
$comparedValue = new \DatetimeImmutable($comparedValue);
} elseif ($value instanceof \DateTime || $value instanceof \DateTimeInterface) {
// Otherwise use DateTime
$comparedValue = new \DateTime($comparedValue);
}
}
if (!$this->compareValues($value, $comparedValue)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value, self::OBJECT_TO_STRING | self::PRETTY_DATE))
->setParameter('{{ compared_value }}', $this->formatValue($comparedValue, self::OBJECT_TO_STRING | self::PRETTY_DATE))
->setParameter('{{ compared_value_type }}', $this->formatTypeOf($comparedValue))
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value, self::OBJECT_TO_STRING | self::PRETTY_DATE))
->setParameter('{{ compared_value }}', $this->formatValue($comparedValue, self::OBJECT_TO_STRING | self::PRETTY_DATE))
->setParameter('{{ compared_value_type }}', $this->formatTypeOf($comparedValue))
->addViolation();
}
}
}
/**
* Compares the two given values to find if their relationship is valid.
*
* @param mixed $value1 The first value to compare
* @param mixed $value2 The second value to compare
*
* @return bool true if the relationship is valid, false otherwise
*/
abstract protected function compareValues($value1, $value2);
}

View file

@ -0,0 +1,40 @@
<?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\Constraints;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class All extends Composite
{
public $constraints = array();
public function getDefaultOption()
{
return 'constraints';
}
public function getRequiredOptions()
{
return array('constraints');
}
protected function getCompositeOption()
{
return 'constraints';
}
}

View file

@ -0,0 +1,58 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class AllValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof All) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\All');
}
if (null === $value) {
return;
}
if (!is_array($value) && !$value instanceof \Traversable) {
throw new UnexpectedTypeException($value, 'array or Traversable');
}
$context = $this->context;
if ($context instanceof ExecutionContextInterface) {
$validator = $context->getValidator()->inContext($context);
foreach ($value as $key => $element) {
$validator->atPath('['.$key.']')->validate($element, $constraint->constraints);
}
} else {
// 2.4 API
foreach ($value as $key => $element) {
$context->validateValue($element, $constraint->constraints, '['.$key.']');
}
}
}
}

View file

@ -0,0 +1,27 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class Blank extends Constraint
{
public $message = 'This value should be blank.';
}

View file

@ -0,0 +1,47 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class BlankValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Blank) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Blank');
}
if ('' !== $value && null !== $value) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}
}

View file

@ -0,0 +1,81 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"CLASS", "PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class Callback extends Constraint
{
/**
* @var string|callable
*
* @since 2.4
*/
public $callback;
/**
* @var array
*
* @deprecated since version 2.4, to be removed in 3.0.
*/
public $methods;
/**
* {@inheritdoc}
*/
public function __construct($options = null)
{
// Invocation through annotations with an array parameter only
if (is_array($options) && 1 === count($options) && isset($options['value'])) {
$options = $options['value'];
}
if (is_array($options) && isset($options['methods'])) {
@trigger_error('The "methods" option of the '.__CLASS__.' class is deprecated since version 2.4 and will be removed in 3.0. Use the "callback" option instead.', E_USER_DEPRECATED);
}
if (is_array($options) && !isset($options['callback']) && !isset($options['methods']) && !isset($options['groups'])) {
if (is_callable($options) || !$options) {
$options = array('callback' => $options);
} else {
// @deprecated, to be removed in 3.0
$options = array('methods' => $options);
}
}
parent::__construct($options);
}
/**
* {@inheritdoc}
*/
public function getDefaultOption()
{
return 'callback';
}
/**
* {@inheritdoc}
*/
public function getTargets()
{
return array(self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT);
}
}

View file

@ -0,0 +1,79 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* Validator for Callback constraint.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class CallbackValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($object, Constraint $constraint)
{
if (!$constraint instanceof Callback) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Callback');
}
if (null !== $constraint->callback && null !== $constraint->methods) {
throw new ConstraintDefinitionException(
'The Callback constraint supports either the option "callback" '.
'or "methods", but not both at the same time.'
);
}
// has to be an array so that we can differentiate between callables
// and method names
if (null !== $constraint->methods && !is_array($constraint->methods)) {
throw new UnexpectedTypeException($constraint->methods, 'array');
}
$methods = $constraint->methods ?: array($constraint->callback);
foreach ($methods as $method) {
if ($method instanceof \Closure) {
$method($object, $this->context);
} elseif (is_array($method)) {
if (!is_callable($method)) {
if (isset($method[0]) && is_object($method[0])) {
$method[0] = get_class($method[0]);
}
throw new ConstraintDefinitionException(sprintf('%s targeted by Callback constraint is not a valid callable', json_encode($method)));
}
call_user_func($method, $object, $this->context);
} elseif (null !== $object) {
if (!method_exists($object, $method)) {
throw new ConstraintDefinitionException(sprintf('Method "%s" targeted by Callback constraint does not exist in class %s', $method, get_class($object)));
}
$reflMethod = new \ReflectionMethod($object, $method);
if ($reflMethod->isStatic()) {
$reflMethod->invoke(null, $object, $this->context);
} else {
$reflMethod->invoke($object, $this->context);
}
}
}
}
}

View file

@ -0,0 +1,47 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* Metadata for the CardSchemeValidator.
*
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Tim Nagel <t.nagel@infinite.net.au>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class CardScheme extends Constraint
{
const NOT_NUMERIC_ERROR = 1;
const INVALID_FORMAT_ERROR = 2;
protected static $errorNames = array(
self::NOT_NUMERIC_ERROR => 'NOT_NUMERIC_ERROR',
self::INVALID_FORMAT_ERROR => 'INVALID_FORMAT_ERROR',
);
public $message = 'Unsupported card type or invalid card number.';
public $schemes;
public function getDefaultOption()
{
return 'schemes';
}
public function getRequiredOptions()
{
return array('schemes');
}
}

View file

@ -0,0 +1,141 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* Validates that a card number belongs to a specified scheme.
*
* @author Tim Nagel <t.nagel@infinite.net.au>
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @see http://en.wikipedia.org/wiki/Bank_card_number
* @see http://www.regular-expressions.info/creditcard.html
* @see http://www.barclaycard.co.uk/business/files/Ranges_and_Rules_September_2014.pdf
*/
class CardSchemeValidator extends ConstraintValidator
{
protected $schemes = array(
// American Express card numbers start with 34 or 37 and have 15 digits.
'AMEX' => array(
'/^3[47][0-9]{13}$/',
),
// China UnionPay cards start with 62 and have between 16 and 19 digits.
// Please note that these cards do not follow Luhn Algorithm as a checksum.
'CHINA_UNIONPAY' => array(
'/^62[0-9]{14,17}$/',
),
// Diners Club card numbers begin with 300 through 305, 36 or 38. All have 14 digits.
// There are Diners Club cards that begin with 5 and have 16 digits.
// These are a joint venture between Diners Club and MasterCard, and should be processed like a MasterCard.
'DINERS' => array(
'/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/',
),
// Discover card numbers begin with 6011, 622126 through 622925, 644 through 649 or 65.
// All have 16 digits.
'DISCOVER' => array(
'/^6011[0-9]{12}$/',
'/^64[4-9][0-9]{13}$/',
'/^65[0-9]{14}$/',
'/^622(12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|91[0-9]|92[0-5])[0-9]{10}$/',
),
// InstaPayment cards begin with 637 through 639 and have 16 digits.
'INSTAPAYMENT' => array(
'/^63[7-9][0-9]{13}$/',
),
// JCB cards beginning with 2131 or 1800 have 15 digits.
// JCB cards beginning with 35 have 16 digits.
'JCB' => array(
'/^(?:2131|1800|35[0-9]{3})[0-9]{11}$/',
),
// Laser cards begin with either 6304, 6706, 6709 or 6771 and have between 16 and 19 digits.
'LASER' => array(
'/^(6304|670[69]|6771)[0-9]{12,15}$/',
),
// Maestro international cards begin with 675900..675999 and have between 12 and 19 digits.
// Maestro UK cards begin with either 500000..509999 or 560000..699999 and have between 12 and 19 digits.
'MAESTRO' => array(
'/^(6759[0-9]{2})[0-9]{6,13}$/',
'/^(50[0-9]{4})[0-9]{6,13}$/',
'/^5[6-9][0-9]{10,17}$/',
'/^6[0-9]{11,18}$/',
),
// All MasterCard numbers start with the numbers 51 through 55. All have 16 digits.
'MASTERCARD' => array(
'/^5[1-5][0-9]{14}$/',
),
// All Visa card numbers start with a 4. New cards have 16 digits. Old cards have 13.
'VISA' => array(
'/^4([0-9]{12}|[0-9]{15})$/',
),
);
/**
* Validates a creditcard belongs to a specified scheme.
*
* @param mixed $value
* @param Constraint $constraint
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof CardScheme) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\CardScheme');
}
if (null === $value || '' === $value) {
return;
}
if (!is_numeric($value)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(CardScheme::NOT_NUMERIC_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(CardScheme::NOT_NUMERIC_ERROR)
->addViolation();
}
return;
}
$schemes = array_flip((array) $constraint->schemes);
$schemeRegexes = array_intersect_key($this->schemes, $schemes);
foreach ($schemeRegexes as $regexes) {
foreach ($regexes as $regex) {
if (preg_match($regex, $value)) {
return;
}
}
}
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(CardScheme::INVALID_FORMAT_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(CardScheme::INVALID_FORMAT_ERROR)
->addViolation();
}
}
}

View file

@ -0,0 +1,54 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class Choice extends Constraint
{
const NO_SUCH_CHOICE_ERROR = 1;
const TOO_FEW_ERROR = 2;
const TOO_MANY_ERROR = 3;
protected static $errorNames = array(
self::NO_SUCH_CHOICE_ERROR => 'NO_SUCH_CHOICE_ERROR',
self::TOO_FEW_ERROR => 'TOO_FEW_ERROR',
self::TOO_MANY_ERROR => 'TOO_MANY_ERROR',
);
public $choices;
public $callback;
public $multiple = false;
public $strict = false;
public $min;
public $max;
public $message = 'The value you selected is not a valid choice.';
public $multipleMessage = 'One or more of the given values is invalid.';
public $minMessage = 'You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.';
public $maxMessage = 'You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.';
/**
* {@inheritdoc}
*/
public function getDefaultOption()
{
return 'choices';
}
}

View file

@ -0,0 +1,135 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* ChoiceValidator validates that the value is one of the expected values.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Florian Eckerstorfer <florian@eckerstorfer.org>
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class ChoiceValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Choice) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Choice');
}
if (!is_array($constraint->choices) && !$constraint->callback) {
throw new ConstraintDefinitionException('Either "choices" or "callback" must be specified on constraint Choice');
}
if (null === $value) {
return;
}
if ($constraint->multiple && !is_array($value)) {
throw new UnexpectedTypeException($value, 'array');
}
if ($constraint->callback) {
if (!is_callable($choices = array($this->context->getClassName(), $constraint->callback))
&& !is_callable($choices = $constraint->callback)
) {
throw new ConstraintDefinitionException('The Choice constraint expects a valid callback');
}
$choices = call_user_func($choices);
} else {
$choices = $constraint->choices;
}
if ($constraint->multiple) {
foreach ($value as $_value) {
if (!in_array($_value, $choices, $constraint->strict)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->multipleMessage)
->setParameter('{{ value }}', $this->formatValue($_value))
->setCode(Choice::NO_SUCH_CHOICE_ERROR)
->setInvalidValue($_value)
->addViolation();
} else {
$this->buildViolation($constraint->multipleMessage)
->setParameter('{{ value }}', $this->formatValue($_value))
->setCode(Choice::NO_SUCH_CHOICE_ERROR)
->setInvalidValue($_value)
->addViolation();
}
return;
}
}
$count = count($value);
if ($constraint->min !== null && $count < $constraint->min) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->minMessage)
->setParameter('{{ limit }}', $constraint->min)
->setPlural((int) $constraint->min)
->setCode(Choice::TOO_FEW_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->minMessage)
->setParameter('{{ limit }}', $constraint->min)
->setPlural((int) $constraint->min)
->setCode(Choice::TOO_FEW_ERROR)
->addViolation();
}
return;
}
if ($constraint->max !== null && $count > $constraint->max) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->maxMessage)
->setParameter('{{ limit }}', $constraint->max)
->setPlural((int) $constraint->max)
->setCode(Choice::TOO_MANY_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->maxMessage)
->setParameter('{{ limit }}', $constraint->max)
->setPlural((int) $constraint->max)
->setCode(Choice::TOO_MANY_ERROR)
->addViolation();
}
return;
}
} elseif (!in_array($value, $choices, $constraint->strict)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Choice::NO_SUCH_CHOICE_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Choice::NO_SUCH_CHOICE_ERROR)
->addViolation();
}
}
}
}

View file

@ -0,0 +1,87 @@
<?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\Constraints;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class Collection extends Composite
{
const MISSING_FIELD_ERROR = 1;
const NO_SUCH_FIELD_ERROR = 2;
protected static $errorNames = array(
self::MISSING_FIELD_ERROR => 'MISSING_FIELD_ERROR',
self::NO_SUCH_FIELD_ERROR => 'NO_SUCH_FIELD_ERROR',
);
public $fields = array();
public $allowExtraFields = false;
public $allowMissingFields = false;
public $extraFieldsMessage = 'This field was not expected.';
public $missingFieldsMessage = 'This field is missing.';
/**
* {@inheritdoc}
*/
public function __construct($options = null)
{
// no known options set? $options is the fields array
if (is_array($options)
&& !array_intersect(array_keys($options), array('groups', 'fields', 'allowExtraFields', 'allowMissingFields', 'extraFieldsMessage', 'missingFieldsMessage'))) {
$options = array('fields' => $options);
}
parent::__construct($options);
}
/**
* {@inheritdoc}
*/
protected function initializeNestedConstraints()
{
parent::initializeNestedConstraints();
if (!is_array($this->fields)) {
throw new ConstraintDefinitionException(sprintf('The option "fields" is expected to be an array in constraint %s', __CLASS__));
}
foreach ($this->fields as $fieldName => $field) {
// the XmlFileLoader and YamlFileLoader pass the field Optional
// and Required constraint as an array with exactly one element
if (is_array($field) && count($field) == 1) {
$this->fields[$fieldName] = $field = $field[0];
}
if (!$field instanceof Optional && !$field instanceof Required) {
$this->fields[$fieldName] = $field = new Required($field);
}
}
}
public function getRequiredOptions()
{
return array('fields');
}
protected function getCompositeOption()
{
return 'fields';
}
}

View file

@ -0,0 +1,29 @@
<?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\Constraints\Collection;
@trigger_error('The '.__NAMESPACE__.'\Optional class is deprecated since version 2.3 and will be removed in 3.0. Use the Symfony\Component\Validator\Constraints\Optional class instead.', E_USER_DEPRECATED);
use Symfony\Component\Validator\Constraints\Optional as BaseOptional;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @deprecated since version 2.3, to be removed in 3.0.
* Use {@link \Symfony\Component\Validator\Constraints\Optional} instead.
*/
class Optional extends BaseOptional
{
}

View file

@ -0,0 +1,29 @@
<?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\Constraints\Collection;
@trigger_error('The '.__NAMESPACE__.'\Required class is deprecated since version 2.3 and will be removed in 3.0. Use the Symfony\Component\Validator\Constraints\Required class instead.', E_USER_DEPRECATED);
use Symfony\Component\Validator\Constraints\Required as BaseRequired;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @deprecated since version 2.3, to be removed in 3.0.
* Use {@link \Symfony\Component\Validator\Constraints\Required} instead.
*/
class Required extends BaseRequired
{
}

View file

@ -0,0 +1,112 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class CollectionValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Collection) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Collection');
}
if (null === $value) {
return;
}
if (!is_array($value) && !($value instanceof \Traversable && $value instanceof \ArrayAccess)) {
throw new UnexpectedTypeException($value, 'array or Traversable and ArrayAccess');
}
// We need to keep the initialized context when CollectionValidator
// calls itself recursively (Collection constraints can be nested).
// Since the context of the validator is overwritten when initialize()
// is called for the nested constraint, the outer validator is
// acting on the wrong context when the nested validation terminates.
//
// A better solution - which should be approached in Symfony 3.0 - is to
// remove the initialize() method and pass the context as last argument
// to validate() instead.
$context = $this->context;
foreach ($constraint->fields as $field => $fieldConstraint) {
// bug fix issue #2779
$existsInArray = is_array($value) && array_key_exists($field, $value);
$existsInArrayAccess = $value instanceof \ArrayAccess && $value->offsetExists($field);
if ($existsInArray || $existsInArrayAccess) {
if (count($fieldConstraint->constraints) > 0) {
if ($context instanceof ExecutionContextInterface) {
$context->getValidator()
->inContext($context)
->atPath('['.$field.']')
->validate($value[$field], $fieldConstraint->constraints);
} else {
// 2.4 API
$context->validateValue($value[$field], $fieldConstraint->constraints, '['.$field.']');
}
}
} elseif (!$fieldConstraint instanceof Optional && !$constraint->allowMissingFields) {
if ($context instanceof ExecutionContextInterface) {
$context->buildViolation($constraint->missingFieldsMessage)
->atPath('['.$field.']')
->setParameter('{{ field }}', $this->formatValue($field))
->setInvalidValue(null)
->setCode(Collection::MISSING_FIELD_ERROR)
->addViolation();
} else {
$this->buildViolationInContext($context, $constraint->missingFieldsMessage)
->atPath('['.$field.']')
->setParameter('{{ field }}', $this->formatValue($field))
->setInvalidValue(null)
->setCode(Collection::MISSING_FIELD_ERROR)
->addViolation();
}
}
}
if (!$constraint->allowExtraFields) {
foreach ($value as $field => $fieldValue) {
if (!isset($constraint->fields[$field])) {
if ($context instanceof ExecutionContextInterface) {
$context->buildViolation($constraint->extraFieldsMessage)
->atPath('['.$field.']')
->setParameter('{{ field }}', $this->formatValue($field))
->setInvalidValue($fieldValue)
->setCode(Collection::NO_SUCH_FIELD_ERROR)
->addViolation();
} else {
$this->buildViolationInContext($context, $constraint->extraFieldsMessage)
->atPath('['.$field.']')
->setParameter('{{ field }}', $this->formatValue($field))
->setInvalidValue($fieldValue)
->setCode(Collection::NO_SUCH_FIELD_ERROR)
->addViolation();
}
}
}
}
}
}

View file

@ -0,0 +1,153 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
/**
* A constraint that is composed of other constraints.
*
* You should never use the nested constraint instances anywhere else, because
* their groups are adapted when passed to the constructor of this class.
*
* If you want to create your own composite constraint, extend this class and
* let {@link getCompositeOption()} return the name of the property which
* contains the nested constraints.
*
* @since 2.6
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
abstract class Composite extends Constraint
{
/**
* {@inheritdoc}
*
* The groups of the composite and its nested constraints are made
* consistent using the following strategy:
*
* - If groups are passed explicitly to the composite constraint, but
* not to the nested constraints, the options of the composite
* constraint are copied to the nested constraints;
*
* - If groups are passed explicitly to the nested constraints, but not
* to the composite constraint, the groups of all nested constraints
* are merged and used as groups for the composite constraint;
*
* - If groups are passed explicitly to both the composite and its nested
* constraints, the groups of the nested constraints must be a subset
* of the groups of the composite constraint. If not, a
* {@link ConstraintDefinitionException} is thrown.
*
* All this is done in the constructor, because constraints can then be
* cached. When constraints are loaded from the cache, no more group
* checks need to be done.
*/
public function __construct($options = null)
{
parent::__construct($options);
$this->initializeNestedConstraints();
/* @var Constraint[] $nestedConstraints */
$compositeOption = $this->getCompositeOption();
$nestedConstraints = $this->$compositeOption;
if (!is_array($nestedConstraints)) {
$nestedConstraints = array($nestedConstraints);
}
foreach ($nestedConstraints as $constraint) {
if (!$constraint instanceof Constraint) {
throw new ConstraintDefinitionException(sprintf('The value %s is not an instance of Constraint in constraint %s', $constraint, get_class($this)));
}
if ($constraint instanceof Valid) {
throw new ConstraintDefinitionException(sprintf('The constraint Valid cannot be nested inside constraint %s. You can only declare the Valid constraint directly on a field or method.', get_class($this)));
}
}
if (!property_exists($this, 'groups')) {
$mergedGroups = array();
foreach ($nestedConstraints as $constraint) {
foreach ($constraint->groups as $group) {
$mergedGroups[$group] = true;
}
}
$this->groups = array_keys($mergedGroups);
$this->$compositeOption = $nestedConstraints;
return;
}
foreach ($nestedConstraints as $constraint) {
if (property_exists($constraint, 'groups')) {
$excessGroups = array_diff($constraint->groups, $this->groups);
if (count($excessGroups) > 0) {
throw new ConstraintDefinitionException(sprintf(
'The group(s) "%s" passed to the constraint %s '.
'should also be passed to its containing constraint %s',
implode('", "', $excessGroups),
get_class($constraint),
get_class($this)
));
}
} else {
$constraint->groups = $this->groups;
}
}
$this->$compositeOption = $nestedConstraints;
}
/**
* {@inheritdoc}
*
* Implicit group names are forwarded to nested constraints.
*
* @param string $group
*/
public function addImplicitGroupName($group)
{
parent::addImplicitGroupName($group);
/** @var Constraint[] $nestedConstraints */
$nestedConstraints = $this->{$this->getCompositeOption()};
foreach ($nestedConstraints as $constraint) {
$constraint->addImplicitGroupName($group);
}
}
/**
* Returns the name of the property that contains the nested constraints.
*
* @return string The property name
*/
abstract protected function getCompositeOption();
/**
* Initializes the nested constraints.
*
* This method can be overwritten in subclasses to clean up the nested
* constraints passed to the constructor.
*
* @see Collection::initializeNestedConstraints()
*/
protected function initializeNestedConstraints()
{
}
}

View file

@ -0,0 +1,56 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\MissingOptionsException;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class Count extends Constraint
{
const TOO_FEW_ERROR = 1;
const TOO_MANY_ERROR = 2;
protected static $errorNames = array(
self::TOO_FEW_ERROR => 'TOO_FEW_ERROR',
self::TOO_MANY_ERROR => 'TOO_MANY_ERROR',
);
public $minMessage = 'This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.';
public $maxMessage = 'This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.';
public $exactMessage = 'This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.';
public $min;
public $max;
public function __construct($options = null)
{
if (null !== $options && !is_array($options)) {
$options = array(
'min' => $options,
'max' => $options,
);
}
parent::__construct($options);
if (null === $this->min && null === $this->max) {
throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max'));
}
}
}

View file

@ -0,0 +1,81 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class CountValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (null === $value) {
return;
}
if (!is_array($value) && !$value instanceof \Countable) {
throw new UnexpectedTypeException($value, 'array or \Countable');
}
$count = count($value);
if (null !== $constraint->max && $count > $constraint->max) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->maxMessage)
->setParameter('{{ count }}', $count)
->setParameter('{{ limit }}', $constraint->max)
->setInvalidValue($value)
->setPlural((int) $constraint->max)
->setCode(Count::TOO_MANY_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->maxMessage)
->setParameter('{{ count }}', $count)
->setParameter('{{ limit }}', $constraint->max)
->setInvalidValue($value)
->setPlural((int) $constraint->max)
->setCode(Count::TOO_MANY_ERROR)
->addViolation();
}
return;
}
if (null !== $constraint->min && $count < $constraint->min) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->minMessage)
->setParameter('{{ count }}', $count)
->setParameter('{{ limit }}', $constraint->min)
->setInvalidValue($value)
->setPlural((int) $constraint->min)
->setCode(Count::TOO_FEW_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->minMessage)
->setParameter('{{ count }}', $count)
->setParameter('{{ limit }}', $constraint->min)
->setInvalidValue($value)
->setPlural((int) $constraint->min)
->setCode(Count::TOO_FEW_ERROR)
->addViolation();
}
}
}
}

View file

@ -0,0 +1,27 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class Country extends Constraint
{
public $message = 'This value is not a valid country.';
}

View file

@ -0,0 +1,61 @@
<?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\Constraints;
use Symfony\Component\Intl\Intl;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* Validates whether a value is a valid country code.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class CountryValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Country) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Country');
}
if (null === $value || '' === $value) {
return;
}
if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedTypeException($value, 'string');
}
$value = (string) $value;
$countries = Intl::getRegionBundle()->getCountryNames();
if (!isset($countries[$value])) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}
}

View file

@ -0,0 +1,27 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Miha Vrhovnik <miha.vrhovnik@pagein.si>
*
* @api
*/
class Currency extends Constraint
{
public $message = 'This value is not a valid currency.';
}

View file

@ -0,0 +1,61 @@
<?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\Constraints;
use Symfony\Component\Intl\Intl;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* Validates whether a value is a valid currency.
*
* @author Miha Vrhovnik <miha.vrhovnik@pagein.si>
*
* @api
*/
class CurrencyValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Currency) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Currency');
}
if (null === $value || '' === $value) {
return;
}
if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedTypeException($value, 'string');
}
$value = (string) $value;
$currencies = Intl::getCurrencyBundle()->getCurrencyNames();
if (!isset($currencies[$value])) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}
}

View file

@ -0,0 +1,35 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class Date extends Constraint
{
const INVALID_FORMAT_ERROR = 1;
const INVALID_DATE_ERROR = 2;
protected static $errorNames = array(
self::INVALID_FORMAT_ERROR => 'INVALID_FORMAT_ERROR',
self::INVALID_DATE_ERROR => 'INVALID_DATE_ERROR',
);
public $message = 'This value is not a valid date.';
}

View file

@ -0,0 +1,37 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class DateTime extends Constraint
{
const INVALID_FORMAT_ERROR = 1;
const INVALID_DATE_ERROR = 2;
const INVALID_TIME_ERROR = 3;
protected static $errorNames = array(
self::INVALID_FORMAT_ERROR => 'INVALID_FORMAT_ERROR',
self::INVALID_DATE_ERROR => 'INVALID_DATE_ERROR',
self::INVALID_TIME_ERROR => 'INVALID_TIME_ERROR',
);
public $message = 'This value is not a valid datetime.';
}

View file

@ -0,0 +1,90 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class DateTimeValidator extends DateValidator
{
const PATTERN = '/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/';
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof DateTime) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\DateTime');
}
if (null === $value || '' === $value || $value instanceof \DateTime) {
return;
}
if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedTypeException($value, 'string');
}
$value = (string) $value;
if (!preg_match(static::PATTERN, $value, $matches)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(DateTime::INVALID_FORMAT_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(DateTime::INVALID_FORMAT_ERROR)
->addViolation();
}
return;
}
if (!DateValidator::checkDate($matches[1], $matches[2], $matches[3])) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(DateTime::INVALID_DATE_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(DateTime::INVALID_DATE_ERROR)
->addViolation();
}
}
if (!TimeValidator::checkTime($matches[4], $matches[5], $matches[6])) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(DateTime::INVALID_TIME_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(DateTime::INVALID_TIME_ERROR)
->addViolation();
}
}
}
}

View file

@ -0,0 +1,93 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class DateValidator extends ConstraintValidator
{
const PATTERN = '/^(\d{4})-(\d{2})-(\d{2})$/';
/**
* Checks whether a date is valid.
*
* @param int $year The year
* @param int $month The month
* @param int $day The day
*
* @return bool Whether the date is valid
*
* @internal
*/
public static function checkDate($year, $month, $day)
{
return checkdate($month, $day, $year);
}
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Date) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Date');
}
if (null === $value || '' === $value || $value instanceof \DateTime) {
return;
}
if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedTypeException($value, 'string');
}
$value = (string) $value;
if (!preg_match(static::PATTERN, $value, $matches)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Date::INVALID_FORMAT_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Date::INVALID_FORMAT_ERROR)
->addViolation();
}
return;
}
if (!self::checkDate($matches[1], $matches[2], $matches[3])) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Date::INVALID_DATE_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Date::INVALID_DATE_ERROR)
->addViolation();
}
}
}
}

View file

@ -0,0 +1,40 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class Email extends Constraint
{
const INVALID_FORMAT_ERROR = 1;
const MX_CHECK_FAILED_ERROR = 2;
const HOST_CHECK_FAILED_ERROR = 3;
protected static $errorNames = array(
self::INVALID_FORMAT_ERROR => 'STRICT_CHECK_FAILED_ERROR',
self::MX_CHECK_FAILED_ERROR => 'MX_CHECK_FAILED_ERROR',
self::HOST_CHECK_FAILED_ERROR => 'HOST_CHECK_FAILED_ERROR',
);
public $message = 'This value is not a valid email address.';
public $checkMX = false;
public $checkHost = false;
public $strict;
}

View file

@ -0,0 +1,157 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\RuntimeException;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class EmailValidator extends ConstraintValidator
{
/**
* @var bool
*/
private $isStrict;
public function __construct($strict = false)
{
$this->isStrict = $strict;
}
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Email) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Email');
}
if (null === $value || '' === $value) {
return;
}
if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedTypeException($value, 'string');
}
$value = (string) $value;
if (null === $constraint->strict) {
$constraint->strict = $this->isStrict;
}
if ($constraint->strict) {
if (!class_exists('\Egulias\EmailValidator\EmailValidator')) {
throw new RuntimeException('Strict email validation requires egulias/email-validator');
}
$strictValidator = new \Egulias\EmailValidator\EmailValidator();
if (!$strictValidator->isValid($value, false, true)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Email::INVALID_FORMAT_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Email::INVALID_FORMAT_ERROR)
->addViolation();
}
return;
}
} elseif (!preg_match('/^.+\@\S+\.\S+$/', $value)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Email::INVALID_FORMAT_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Email::INVALID_FORMAT_ERROR)
->addViolation();
}
return;
}
$host = substr($value, strpos($value, '@') + 1);
// Check for host DNS resource records
if ($constraint->checkMX) {
if (!$this->checkMX($host)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Email::MX_CHECK_FAILED_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Email::MX_CHECK_FAILED_ERROR)
->addViolation();
}
}
return;
}
if ($constraint->checkHost && !$this->checkHost($host)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Email::HOST_CHECK_FAILED_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Email::HOST_CHECK_FAILED_ERROR)
->addViolation();
}
}
}
/**
* Check DNS Records for MX type.
*
* @param string $host Host
*
* @return bool
*/
private function checkMX($host)
{
return checkdnsrr($host, 'MX');
}
/**
* Check if one of MX, A or AAAA DNS RR exists.
*
* @param string $host Host
*
* @return bool
*/
private function checkHost($host)
{
return $this->checkMX($host) || (checkdnsrr($host, 'A') || checkdnsrr($host, 'AAAA'));
}
}

View file

@ -0,0 +1,23 @@
<?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\Constraints;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Daniel Holmes <daniel@danielholmes.org>
*/
class EqualTo extends AbstractComparison
{
public $message = 'This value should be equal to {{ compared_value }}.';
}

View file

@ -0,0 +1,28 @@
<?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\Constraints;
/**
* Validates values are equal (==).
*
* @author Daniel Holmes <daniel@danielholmes.org>
*/
class EqualToValidator extends AbstractComparisonValidator
{
/**
* {@inheritdoc}
*/
protected function compareValues($value1, $value2)
{
return $value1 == $value2;
}
}

View file

@ -0,0 +1,30 @@
<?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\Constraints;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
abstract class Existence extends Composite
{
public $constraints = array();
public function getDefaultOption()
{
return 'constraints';
}
protected function getCompositeOption()
{
return 'constraints';
}
}

View file

@ -0,0 +1,59 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"CLASS", "PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class Expression extends Constraint
{
public $message = 'This value is not valid.';
public $expression;
/**
* {@inheritdoc}
*/
public function getDefaultOption()
{
return 'expression';
}
/**
* {@inheritdoc}
*/
public function getRequiredOptions()
{
return array('expression');
}
/**
* {@inheritdoc}
*/
public function getTargets()
{
return array(self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT);
}
/**
* {@inheritdoc}
*/
public function validatedBy()
{
return 'validator.expression';
}
}

View file

@ -0,0 +1,123 @@
<?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\Constraints;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Exception\RuntimeException;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Fabien Potencier <fabien@symfony.com>
* @author Bernhard Schussek <bschussek@symfony.com>
*/
class ExpressionValidator extends ConstraintValidator
{
/**
* @var PropertyAccessorInterface
*/
private $propertyAccessor;
/**
* @var ExpressionLanguage
*/
private $expressionLanguage;
/**
* @param PropertyAccessorInterface|null $propertyAccessor Optional as of Symfony 2.5
*
* @throws UnexpectedTypeException If the property accessor is invalid
*/
public function __construct($propertyAccessor = null)
{
if (null !== $propertyAccessor && !$propertyAccessor instanceof PropertyAccessorInterface) {
throw new UnexpectedTypeException($propertyAccessor, 'null or \Symfony\Component\PropertyAccess\PropertyAccessorInterface');
}
$this->propertyAccessor = $propertyAccessor;
}
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Expression) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Expression');
}
$variables = array();
// Symfony 2.5+
if ($this->context instanceof ExecutionContextInterface) {
$variables['value'] = $value;
$variables['this'] = $this->context->getObject();
} elseif (null === $this->context->getPropertyName()) {
$variables['value'] = $value;
$variables['this'] = $value;
} else {
$root = $this->context->getRoot();
$variables['value'] = $value;
if (is_object($root)) {
// Extract the object that the property belongs to from the object
// graph
$path = new PropertyPath($this->context->getPropertyPath());
$parentPath = $path->getParent();
$variables['this'] = $parentPath ? $this->getPropertyAccessor()->getValue($root, $parentPath) : $root;
} else {
$variables['this'] = null;
}
}
if (!$this->getExpressionLanguage()->evaluate($constraint->expression, $variables)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}
private function getExpressionLanguage()
{
if (null === $this->expressionLanguage) {
if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
}
$this->expressionLanguage = new ExpressionLanguage();
}
return $this->expressionLanguage;
}
private function getPropertyAccessor()
{
if (null === $this->propertyAccessor) {
if (!class_exists('Symfony\Component\PropertyAccess\PropertyAccess')) {
throw new RuntimeException('Unable to use expressions as the Symfony PropertyAccess component is not installed.');
}
$this->propertyAccessor = PropertyAccess::createPropertyAccessor();
}
return $this->propertyAccessor;
}
}

View file

@ -0,0 +1,26 @@
<?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\Constraints;
@trigger_error('The '.__NAMESPACE__.'\False class is deprecated since version 2.7 and will be removed in 3.0. Use the IsFalse class in the same namespace instead.', E_USER_DEPRECATED);
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @deprecated since version 2.7, to be removed in 3.0. Use IsFalse instead.
*/
class False extends IsFalse
{
}

View file

@ -0,0 +1,23 @@
<?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\Constraints;
@trigger_error('The '.__NAMESPACE__.'\FalseValidator class is deprecated since version 2.7 and will be removed in 3.0. Use the IsFalseValidator class in the same namespace instead.', E_USER_DEPRECATED);
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @deprecated since version 2.7, to be removed in 3.0. Use IsFalseValidator instead.
*/
class FalseValidator extends IsFalseValidator
{
}

View file

@ -0,0 +1,112 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class File extends Constraint
{
// Check the Image constraint for clashes if adding new constants here
const NOT_FOUND_ERROR = 1;
const NOT_READABLE_ERROR = 2;
const EMPTY_ERROR = 3;
const TOO_LARGE_ERROR = 4;
const INVALID_MIME_TYPE_ERROR = 5;
protected static $errorNames = array(
self::NOT_FOUND_ERROR => 'NOT_FOUND_ERROR',
self::NOT_READABLE_ERROR => 'NOT_READABLE_ERROR',
self::EMPTY_ERROR => 'EMPTY_ERROR',
self::TOO_LARGE_ERROR => 'TOO_LARGE_ERROR',
self::INVALID_MIME_TYPE_ERROR => 'INVALID_MIME_TYPE_ERROR',
);
public $binaryFormat;
public $mimeTypes = array();
public $notFoundMessage = 'The file could not be found.';
public $notReadableMessage = 'The file is not readable.';
public $maxSizeMessage = 'The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.';
public $mimeTypesMessage = 'The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.';
public $disallowEmptyMessage = 'An empty file is not allowed.';
public $uploadIniSizeErrorMessage = 'The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.';
public $uploadFormSizeErrorMessage = 'The file is too large.';
public $uploadPartialErrorMessage = 'The file was only partially uploaded.';
public $uploadNoFileErrorMessage = 'No file was uploaded.';
public $uploadNoTmpDirErrorMessage = 'No temporary folder was configured in php.ini.';
public $uploadCantWriteErrorMessage = 'Cannot write temporary file to disk.';
public $uploadExtensionErrorMessage = 'A PHP extension caused the upload to fail.';
public $uploadErrorMessage = 'The file could not be uploaded.';
protected $maxSize;
public function __construct($options = null)
{
parent::__construct($options);
if (null !== $this->maxSize) {
$this->normalizeBinaryFormat($this->maxSize);
}
}
public function __set($option, $value)
{
if ('maxSize' === $option) {
$this->normalizeBinaryFormat($value);
return;
}
parent::__set($option, $value);
}
public function __get($option)
{
if ('maxSize' === $option) {
return $this->maxSize;
}
return parent::__get($option);
}
private function normalizeBinaryFormat($maxSize)
{
if (ctype_digit((string) $maxSize)) {
$this->maxSize = (int) $maxSize;
$this->binaryFormat = null === $this->binaryFormat ? false : $this->binaryFormat;
} elseif (preg_match('/^\d++k$/i', $maxSize)) {
$this->maxSize = $maxSize * 1000;
$this->binaryFormat = null === $this->binaryFormat ? false : $this->binaryFormat;
} elseif (preg_match('/^\d++M$/i', $maxSize)) {
$this->maxSize = $maxSize * 1000000;
$this->binaryFormat = null === $this->binaryFormat ? false : $this->binaryFormat;
} elseif (preg_match('/^\d++Ki$/i', $maxSize)) {
$this->maxSize = $maxSize << 10;
$this->binaryFormat = null === $this->binaryFormat ? true : $this->binaryFormat;
} elseif (preg_match('/^\d++Mi$/i', $maxSize)) {
$this->maxSize = $maxSize << 20;
$this->binaryFormat = null === $this->binaryFormat ? true : $this->binaryFormat;
} else {
throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum size', $this->maxSize));
}
}
}

View file

@ -0,0 +1,331 @@
<?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\Constraints;
use Symfony\Component\HttpFoundation\File\File as FileObject;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class FileValidator extends ConstraintValidator
{
const KB_BYTES = 1000;
const MB_BYTES = 1000000;
const KIB_BYTES = 1024;
const MIB_BYTES = 1048576;
private static $suffices = array(
1 => 'bytes',
self::KB_BYTES => 'kB',
self::MB_BYTES => 'MB',
self::KIB_BYTES => 'KiB',
self::MIB_BYTES => 'MiB',
);
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof File) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\File');
}
if (null === $value || '' === $value) {
return;
}
if ($value instanceof UploadedFile && !$value->isValid()) {
switch ($value->getError()) {
case UPLOAD_ERR_INI_SIZE:
$iniLimitSize = UploadedFile::getMaxFilesize();
if ($constraint->maxSize && $constraint->maxSize < $iniLimitSize) {
$limitInBytes = $constraint->maxSize;
$binaryFormat = $constraint->binaryFormat;
} else {
$limitInBytes = $iniLimitSize;
$binaryFormat = true;
}
list($sizeAsString, $limitAsString, $suffix) = $this->factorizeSizes(0, $limitInBytes, $binaryFormat);
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->uploadIniSizeErrorMessage)
->setParameter('{{ limit }}', $limitAsString)
->setParameter('{{ suffix }}', $suffix)
->setCode(UPLOAD_ERR_INI_SIZE)
->addViolation();
} else {
$this->buildViolation($constraint->uploadIniSizeErrorMessage)
->setParameter('{{ limit }}', $limitAsString)
->setParameter('{{ suffix }}', $suffix)
->setCode(UPLOAD_ERR_INI_SIZE)
->addViolation();
}
return;
case UPLOAD_ERR_FORM_SIZE:
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->uploadFormSizeErrorMessage)
->setCode(UPLOAD_ERR_FORM_SIZE)
->addViolation();
} else {
$this->buildViolation($constraint->uploadFormSizeErrorMessage)
->setCode(UPLOAD_ERR_FORM_SIZE)
->addViolation();
}
return;
case UPLOAD_ERR_PARTIAL:
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->uploadPartialErrorMessage)
->setCode(UPLOAD_ERR_PARTIAL)
->addViolation();
} else {
$this->buildViolation($constraint->uploadPartialErrorMessage)
->setCode(UPLOAD_ERR_PARTIAL)
->addViolation();
}
return;
case UPLOAD_ERR_NO_FILE:
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->uploadNoFileErrorMessage)
->setCode(UPLOAD_ERR_NO_FILE)
->addViolation();
} else {
$this->buildViolation($constraint->uploadNoFileErrorMessage)
->setCode(UPLOAD_ERR_NO_FILE)
->addViolation();
}
return;
case UPLOAD_ERR_NO_TMP_DIR:
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->uploadNoTmpDirErrorMessage)
->setCode(UPLOAD_ERR_NO_TMP_DIR)
->addViolation();
} else {
$this->buildViolation($constraint->uploadNoTmpDirErrorMessage)
->setCode(UPLOAD_ERR_NO_TMP_DIR)
->addViolation();
}
return;
case UPLOAD_ERR_CANT_WRITE:
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->uploadCantWriteErrorMessage)
->setCode(UPLOAD_ERR_CANT_WRITE)
->addViolation();
} else {
$this->buildViolation($constraint->uploadCantWriteErrorMessage)
->setCode(UPLOAD_ERR_CANT_WRITE)
->addViolation();
}
return;
case UPLOAD_ERR_EXTENSION:
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->uploadExtensionErrorMessage)
->setCode(UPLOAD_ERR_EXTENSION)
->addViolation();
} else {
$this->buildViolation($constraint->uploadExtensionErrorMessage)
->setCode(UPLOAD_ERR_EXTENSION)
->addViolation();
}
return;
default:
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->uploadErrorMessage)
->setCode($value->getError())
->addViolation();
} else {
$this->buildViolation($constraint->uploadErrorMessage)
->setCode($value->getError())
->addViolation();
}
return;
}
}
if (!is_scalar($value) && !$value instanceof FileObject && !(is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedTypeException($value, 'string');
}
$path = $value instanceof FileObject ? $value->getPathname() : (string) $value;
if (!is_file($path)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->notFoundMessage)
->setParameter('{{ file }}', $this->formatValue($path))
->setCode(File::NOT_FOUND_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->notFoundMessage)
->setParameter('{{ file }}', $this->formatValue($path))
->setCode(File::NOT_FOUND_ERROR)
->addViolation();
}
return;
}
if (!is_readable($path)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->notReadableMessage)
->setParameter('{{ file }}', $this->formatValue($path))
->setCode(File::NOT_READABLE_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->notReadableMessage)
->setParameter('{{ file }}', $this->formatValue($path))
->setCode(File::NOT_READABLE_ERROR)
->addViolation();
}
return;
}
$sizeInBytes = filesize($path);
if (0 === $sizeInBytes) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->disallowEmptyMessage)
->setParameter('{{ file }}', $this->formatValue($path))
->setCode(File::EMPTY_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->disallowEmptyMessage)
->setParameter('{{ file }}', $this->formatValue($path))
->setCode(File::EMPTY_ERROR)
->addViolation();
}
return;
}
if ($constraint->maxSize) {
$limitInBytes = $constraint->maxSize;
if ($sizeInBytes > $limitInBytes) {
list($sizeAsString, $limitAsString, $suffix) = $this->factorizeSizes($sizeInBytes, $limitInBytes, $constraint->binaryFormat);
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->maxSizeMessage)
->setParameter('{{ file }}', $this->formatValue($path))
->setParameter('{{ size }}', $sizeAsString)
->setParameter('{{ limit }}', $limitAsString)
->setParameter('{{ suffix }}', $suffix)
->setCode(File::TOO_LARGE_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->maxSizeMessage)
->setParameter('{{ file }}', $this->formatValue($path))
->setParameter('{{ size }}', $sizeAsString)
->setParameter('{{ limit }}', $limitAsString)
->setParameter('{{ suffix }}', $suffix)
->setCode(File::TOO_LARGE_ERROR)
->addViolation();
}
return;
}
}
if ($constraint->mimeTypes) {
if (!$value instanceof FileObject) {
$value = new FileObject($value);
}
$mimeTypes = (array) $constraint->mimeTypes;
$mime = $value->getMimeType();
foreach ($mimeTypes as $mimeType) {
if ($mimeType === $mime) {
return;
}
if ($discrete = strstr($mimeType, '/*', true)) {
if (strstr($mime, '/', true) === $discrete) {
return;
}
}
}
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->mimeTypesMessage)
->setParameter('{{ file }}', $this->formatValue($path))
->setParameter('{{ type }}', $this->formatValue($mime))
->setParameter('{{ types }}', $this->formatValues($mimeTypes))
->setCode(File::INVALID_MIME_TYPE_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->mimeTypesMessage)
->setParameter('{{ file }}', $this->formatValue($path))
->setParameter('{{ type }}', $this->formatValue($mime))
->setParameter('{{ types }}', $this->formatValues($mimeTypes))
->setCode(File::INVALID_MIME_TYPE_ERROR)
->addViolation();
}
}
}
private static function moreDecimalsThan($double, $numberOfDecimals)
{
return strlen((string) $double) > strlen(round($double, $numberOfDecimals));
}
/**
* Convert the limit to the smallest possible number
* (i.e. try "MB", then "kB", then "bytes").
*/
private function factorizeSizes($size, $limit, $binaryFormat)
{
if ($binaryFormat) {
$coef = self::MIB_BYTES;
$coefFactor = self::KIB_BYTES;
} else {
$coef = self::MB_BYTES;
$coefFactor = self::KB_BYTES;
}
$limitAsString = (string) ($limit / $coef);
// Restrict the limit to 2 decimals (without rounding! we
// need the precise value)
while (self::moreDecimalsThan($limitAsString, 2)) {
$coef /= $coefFactor;
$limitAsString = (string) ($limit / $coef);
}
// Convert size to the same measure, but round to 2 decimals
$sizeAsString = (string) round($size / $coef, 2);
// If the size and limit produce the same string output
// (due to rounding), reduce the coefficient
while ($sizeAsString === $limitAsString) {
$coef /= $coefFactor;
$limitAsString = (string) ($limit / $coef);
$sizeAsString = (string) round($size / $coef, 2);
}
return array($sizeAsString, $limitAsString, self::$suffices[$coef]);
}
}

View file

@ -0,0 +1,23 @@
<?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\Constraints;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Daniel Holmes <daniel@danielholmes.org>
*/
class GreaterThan extends AbstractComparison
{
public $message = 'This value should be greater than {{ compared_value }}.';
}

View file

@ -0,0 +1,23 @@
<?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\Constraints;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Daniel Holmes <daniel@danielholmes.org>
*/
class GreaterThanOrEqual extends AbstractComparison
{
public $message = 'This value should be greater than or equal to {{ compared_value }}.';
}

View file

@ -0,0 +1,28 @@
<?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\Constraints;
/**
* Validates values are greater than or equal to the previous (>=).
*
* @author Daniel Holmes <daniel@danielholmes.org>
*/
class GreaterThanOrEqualValidator extends AbstractComparisonValidator
{
/**
* {@inheritdoc}
*/
protected function compareValues($value1, $value2)
{
return $value1 >= $value2;
}
}

View file

@ -0,0 +1,28 @@
<?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\Constraints;
/**
* Validates values are greater than the previous (>).
*
* @author Daniel Holmes <daniel@danielholmes.org>
*/
class GreaterThanValidator extends AbstractComparisonValidator
{
/**
* {@inheritdoc}
*/
protected function compareValues($value1, $value2)
{
return $value1 > $value2;
}
}

View file

@ -0,0 +1,213 @@
<?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\Constraints;
use Symfony\Component\Validator\Exception\OutOfBoundsException;
/**
* A sequence of validation groups.
*
* When validating a group sequence, each group will only be validated if all
* of the previous groups in the sequence succeeded. For example:
*
* $validator->validate($address, null, new GroupSequence('Basic', 'Strict'));
*
* In the first step, all constraints that belong to the group "Basic" will be
* validated. If none of the constraints fail, the validator will then validate
* the constraints in group "Strict". This is useful, for example, if "Strict"
* contains expensive checks that require a lot of CPU or slow, external
* services. You usually don't want to run expensive checks if any of the cheap
* checks fail.
*
* When adding metadata to a class, you can override the "Default" group of
* that class with a group sequence:
*
* /**
* * @GroupSequence({"Address", "Strict"})
* *\/
* class Address
* {
* // ...
* }
*
* Whenever you validate that object in the "Default" group, the group sequence
* will be validated:
*
* $validator->validate($address);
*
* If you want to execute the constraints of the "Default" group for a class
* with an overridden default group, pass the class name as group name instead:
*
* $validator->validate($address, null, "Address")
*
* @Annotation
* @Target({"CLASS", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*
* Implementing \ArrayAccess, \IteratorAggregate and \Countable is @deprecated since 2.5 and will be removed in 3.0.
*/
class GroupSequence implements \ArrayAccess, \IteratorAggregate, \Countable
{
/**
* The groups in the sequence.
*
* @var string[]|GroupSequence[]
*/
public $groups;
/**
* The group in which cascaded objects are validated when validating
* this sequence.
*
* By default, cascaded objects are validated in each of the groups of
* the sequence.
*
* If a class has a group sequence attached, that sequence replaces the
* "Default" group. When validating that class in the "Default" group, the
* group sequence is used instead, but still the "Default" group should be
* cascaded to other objects.
*
* @var string|GroupSequence
*/
public $cascadedGroup;
/**
* Creates a new group sequence.
*
* @param string[] $groups The groups in the sequence
*/
public function __construct(array $groups)
{
// Support for Doctrine annotations
$this->groups = isset($groups['value']) ? $groups['value'] : $groups;
}
/**
* Returns an iterator for this group.
*
* Implemented for backwards compatibility with Symfony < 2.5.
*
* @return \Traversable The iterator
*
* @see \IteratorAggregate::getIterator()
* @deprecated since version 2.5, to be removed in 3.0.
*/
public function getIterator()
{
@trigger_error('The '.__METHOD__.' method is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
return new \ArrayIterator($this->groups);
}
/**
* Returns whether the given offset exists in the sequence.
*
* Implemented for backwards compatibility with Symfony < 2.5.
*
* @param int $offset The offset
*
* @return bool Whether the offset exists
*
* @deprecated since version 2.5, to be removed in 3.0.
*/
public function offsetExists($offset)
{
@trigger_error('The '.__METHOD__.' method is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
return isset($this->groups[$offset]);
}
/**
* Returns the group at the given offset.
*
* Implemented for backwards compatibility with Symfony < 2.5.
*
* @param int $offset The offset
*
* @return string The group a the given offset
*
* @throws OutOfBoundsException If the object does not exist
*
* @deprecated since version 2.5, to be removed in 3.0.
*/
public function offsetGet($offset)
{
@trigger_error('The '.__METHOD__.' method is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
if (!isset($this->groups[$offset])) {
throw new OutOfBoundsException(sprintf(
'The offset "%s" does not exist.',
$offset
));
}
return $this->groups[$offset];
}
/**
* Sets the group at the given offset.
*
* Implemented for backwards compatibility with Symfony < 2.5.
*
* @param int $offset The offset
* @param string $value The group name
*
* @deprecated since version 2.5, to be removed in 3.0.
*/
public function offsetSet($offset, $value)
{
@trigger_error('The '.__METHOD__.' method is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
if (null !== $offset) {
$this->groups[$offset] = $value;
return;
}
$this->groups[] = $value;
}
/**
* Removes the group at the given offset.
*
* Implemented for backwards compatibility with Symfony < 2.5.
*
* @param int $offset The offset
*
* @deprecated since version 2.5, to be removed in 3.0.
*/
public function offsetUnset($offset)
{
@trigger_error('The '.__METHOD__.' method is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
unset($this->groups[$offset]);
}
/**
* Returns the number of groups in the sequence.
*
* Implemented for backwards compatibility with Symfony < 2.5.
*
* @return int The number of groups
*
* @deprecated since version 2.5, to be removed in 3.0.
*/
public function count()
{
@trigger_error('The '.__METHOD__.' method is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
return count($this->groups);
}
}

View file

@ -0,0 +1,22 @@
<?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\Constraints;
/**
* Annotation to define a group sequence provider.
*
* @Annotation
* @Target({"CLASS", "ANNOTATION"})
*/
class GroupSequenceProvider
{
}

View file

@ -0,0 +1,47 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Manuel Reinhard <manu@sprain.ch>
* @author Michael Schummel
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class Iban extends Constraint
{
/** @deprecated, to be removed in 3.0. */
const TOO_SHORT_ERROR = 1;
const INVALID_COUNTRY_CODE_ERROR = 2;
const INVALID_CHARACTERS_ERROR = 3;
/** @deprecated, to be removed in 3.0. */
const INVALID_CASE_ERROR = 4;
const CHECKSUM_FAILED_ERROR = 5;
const INVALID_FORMAT_ERROR = 6;
const NOT_SUPPORTED_COUNTRY_CODE_ERROR = 7;
protected static $errorNames = array(
self::TOO_SHORT_ERROR => 'TOO_SHORT_ERROR',
self::INVALID_COUNTRY_CODE_ERROR => 'INVALID_COUNTRY_CODE_ERROR',
self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR',
self::INVALID_CASE_ERROR => 'INVALID_CASE_ERROR',
self::CHECKSUM_FAILED_ERROR => 'CHECKSUM_FAILED_ERROR',
self::INVALID_FORMAT_ERROR => 'INVALID_FORMAT_ERROR',
self::NOT_SUPPORTED_COUNTRY_CODE_ERROR => 'NOT_SUPPORTED_COUNTRY_CODE_ERROR',
);
public $message = 'This is not a valid International Bank Account Number (IBAN).';
}

View file

@ -0,0 +1,294 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Manuel Reinhard <manu@sprain.ch>
* @author Michael Schummel
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @link http://www.michael-schummel.de/2007/10/05/iban-prufung-mit-php/
*/
class IbanValidator extends ConstraintValidator
{
/**
* IBAN country specific formats.
*
* The first 2 characters from an IBAN format are the two-character ISO country code.
* The following 2 characters represent the check digits calculated from the rest of the IBAN characters.
* The rest are up to thirty alphanumeric characters for
* a BBAN (Basic Bank Account Number) which has a fixed length per country and,
* included within it, a bank identifier with a fixed position and a fixed length per country
*
* @link http://www.swift.com/dsp/resources/documents/IBAN_Registry.pdf
*
* @var array
*/
private static $formats = array(
'AD' => 'AD\d{2}\d{4}\d{4}[\dA-Z]{12}', // Andorra
'AE' => 'AE\d{2}\d{3}\d{16}', // United Arab Emirates
'AL' => 'AL\d{2}\d{8}[\dA-Z]{16}', // Albania
'AO' => 'AO\d{2}\d{21}', // Angola
'AT' => 'AT\d{2}\d{5}\d{11}', // Austria
'AX' => 'FI\d{2}\d{6}\d{7}\d{1}', // Aland Islands
'AZ' => 'AZ\d{2}[A-Z]{4}[\dA-Z]{20}', // Azerbaijan
'BA' => 'BA\d{2}\d{3}\d{3}\d{8}\d{2}', // Bosnia and Herzegovina
'BE' => 'BE\d{2}\d{3}\d{7}\d{2}', // Belgium
'BF' => 'BF\d{2}\d{23}', // Burkina Faso
'BG' => 'BG\d{2}[A-Z]{4}\d{4}\d{2}[\dA-Z]{8}', // Bulgaria
'BH' => 'BH\d{2}[A-Z]{4}[\dA-Z]{14}', // Bahrain
'BI' => 'BI\d{2}\d{12}', // Burundi
'BJ' => 'BJ\d{2}[A-Z]{1}\d{23}', // Benin
'BL' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Saint Barthelemy
'BR' => 'BR\d{2}\d{8}\d{5}\d{10}[A-Z][\dA-Z]', // Brazil
'CG' => 'CG\d{2}\d{23}', // Congo
'CH' => 'CH\d{2}\d{5}[\dA-Z]{12}', // Switzerland
'CI' => 'CI\d{2}[A-Z]{1}\d{23}', // Ivory Coast
'CM' => 'CM\d{2}\d{23}', // Cameron
'CR' => 'CR\d{2}\d{3}\d{14}', // Costa Rica
'CV' => 'CV\d{2}\d{21}', // Cape Verde
'CY' => 'CY\d{2}\d{3}\d{5}[\dA-Z]{16}', // Cyprus
'CZ' => 'CZ\d{2}\d{20}', // Czech Republic
'DE' => 'DE\d{2}\d{8}\d{10}', // Germany
'DO' => 'DO\d{2}[\dA-Z]{4}\d{20}', // Dominican Republic
'DK' => 'DK\d{2}\d{4}\d{10}', // Denmark
'DZ' => 'DZ\d{2}\d{20}', // Algeria
'EE' => 'EE\d{2}\d{2}\d{2}\d{11}\d{1}', // Estonia
'ES' => 'ES\d{2}\d{4}\d{4}\d{1}\d{1}\d{10}', // Spain (also includes Canary Islands, Ceuta and Melilla)
'FI' => 'FI\d{2}\d{6}\d{7}\d{1}', // Finland
'FO' => 'FO\d{2}\d{4}\d{9}\d{1}', // Faroe Islands
'FR' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // France
'GF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // French Guyana
'GB' => 'GB\d{2}[A-Z]{4}\d{6}\d{8}', // United Kingdom of Great Britain and Northern Ireland
'GE' => 'GE\d{2}[A-Z]{2}\d{16}', // Georgia
'GI' => 'GI\d{2}[A-Z]{4}[\dA-Z]{15}', // Gibraltar
'GL' => 'GL\d{2}\d{4}\d{9}\d{1}', // Greenland
'GP' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Guadeloupe
'GR' => 'GR\d{2}\d{3}\d{4}[\dA-Z]{16}', // Greece
'GT' => 'GT\d{2}[\dA-Z]{4}[\dA-Z]{20}', // Guatemala
'HR' => 'HR\d{2}\d{7}\d{10}', // Croatia
'HU' => 'HU\d{2}\d{3}\d{4}\d{1}\d{15}\d{1}', // Hungary
'IE' => 'IE\d{2}[A-Z]{4}\d{6}\d{8}', // Ireland
'IL' => 'IL\d{2}\d{3}\d{3}\d{13}', // Israel
'IR' => 'IR\d{2}\d{22}', // Iran
'IS' => 'IS\d{2}\d{4}\d{2}\d{6}\d{10}', // Iceland
'IT' => 'IT\d{2}[A-Z]{1}\d{5}\d{5}[\dA-Z]{12}', // Italy
'JO' => 'JO\d{2}[A-Z]{4}\d{4}[\dA-Z]{18}', // Jordan
'KW' => 'KW\d{2}[A-Z]{4}\d{22}', // KUWAIT
'KZ' => 'KZ\d{2}\d{3}[\dA-Z]{13}', // Kazakhstan
'LB' => 'LB\d{2}\d{4}[\dA-Z]{20}', // LEBANON
'LI' => 'LI\d{2}\d{5}[\dA-Z]{12}', // Liechtenstein (Principality of)
'LT' => 'LT\d{2}\d{5}\d{11}', // Lithuania
'LU' => 'LU\d{2}\d{3}[\dA-Z]{13}', // Luxembourg
'LV' => 'LV\d{2}[A-Z]{4}[\dA-Z]{13}', // Latvia
'MC' => 'MC\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Monaco
'MD' => 'MD\d{2}[\dA-Z]{2}[\dA-Z]{18}', // Moldova
'ME' => 'ME\d{2}\d{3}\d{13}\d{2}', // Montenegro
'MF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Saint Martin (French part)
'MG' => 'MG\d{2}\d{23}', // Madagascar
'MK' => 'MK\d{2}\d{3}[\dA-Z]{10}\d{2}', // Macedonia, Former Yugoslav Republic of
'ML' => 'ML\d{2}[A-Z]{1}\d{23}', // Mali
'MQ' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Martinique
'MR' => 'MR13\d{5}\d{5}\d{11}\d{2}', // Mauritania
'MT' => 'MT\d{2}[A-Z]{4}\d{5}[\dA-Z]{18}', // Malta
'MU' => 'MU\d{2}[A-Z]{4}\d{2}\d{2}\d{12}\d{3}[A-Z]{3}', // Mauritius
'MZ' => 'MZ\d{2}\d{21}', // Mozambique
'NC' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // New Caledonia
'NL' => 'NL\d{2}[A-Z]{4}\d{10}', // The Netherlands
'NO' => 'NO\d{2}\d{4}\d{6}\d{1}', // Norway
'PF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // French Polynesia
'PK' => 'PK\d{2}[A-Z]{4}[\dA-Z]{16}', // Pakistan
'PL' => 'PL\d{2}\d{8}\d{16}', // Poland
'PM' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Saint Pierre et Miquelon
'PS' => 'PS\d{2}[A-Z]{4}[\dA-Z]{21}', // Palestine, State of
'PT' => 'PT\d{2}\d{4}\d{4}\d{11}\d{2}', // Portugal (plus Azores and Madeira)
'QA' => 'QA\d{2}[A-Z]{4}[\dA-Z]{21}', // Qatar
'RE' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Reunion
'RO' => 'RO\d{2}[A-Z]{4}[\dA-Z]{16}', // Romania
'RS' => 'RS\d{2}\d{3}\d{13}\d{2}', // Serbia
'SA' => 'SA\d{2}\d{2}[\dA-Z]{18}', // Saudi Arabia
'SE' => 'SE\d{2}\d{3}\d{16}\d{1}', // Sweden
'SI' => 'SI\d{2}\d{5}\d{8}\d{2}', // Slovenia
'SK' => 'SK\d{2}\d{4}\d{6}\d{10}', // Slovak Republic
'SM' => 'SM\d{2}[A-Z]{1}\d{5}\d{5}[\dA-Z]{12}', // San Marino
'SN' => 'SN\d{2}[A-Z]{1}\d{23}', // Senegal
'TF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // French Southern Territories
'TL' => 'TL\d{2}\d{3}\d{14}\d{2}', // Timor-Leste
'TN' => 'TN59\d{2}\d{3}\d{13}\d{2}', // Tunisia
'TR' => 'TR\d{2}\d{5}[\dA-Z]{1}[\dA-Z]{16}', // Turkey
'UA' => 'UA\d{2}[A-Z]{6}[\dA-Z]{19}', // Ukraine
'VG' => 'VG\d{2}[A-Z]{4}\d{16}', // Virgin Islands, British
'WF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Wallis and Futuna Islands
'XK' => 'XK\d{2}\d{4}\d{10}\d{2}', // Republic of Kosovo
'YT' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Mayotte
);
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Iban) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Iban');
}
if (null === $value || '' === $value) {
return;
}
if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedTypeException($value, 'string');
}
$value = (string) $value;
// Remove spaces and convert to uppercase
$canonicalized = str_replace(' ', '', strtoupper($value));
// The IBAN must contain only digits and characters...
if (!ctype_alnum($canonicalized)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Iban::INVALID_CHARACTERS_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Iban::INVALID_CHARACTERS_ERROR)
->addViolation();
}
return;
}
// ...start with a two-letter country code
$countryCode = substr($canonicalized, 0, 2);
if (!ctype_alpha($countryCode)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Iban::INVALID_COUNTRY_CODE_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Iban::INVALID_COUNTRY_CODE_ERROR)
->addViolation();
}
return;
}
// ...have a format available
if (!array_key_exists($countryCode, self::$formats)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Iban::NOT_SUPPORTED_COUNTRY_CODE_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Iban::NOT_SUPPORTED_COUNTRY_CODE_ERROR)
->addViolation();
}
return;
}
// ...and have a valid format
if (!preg_match('/^'.self::$formats[$countryCode].'$/', $canonicalized)
) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Iban::INVALID_FORMAT_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Iban::INVALID_FORMAT_ERROR)
->addViolation();
}
return;
}
// Move the first four characters to the end
// e.g. CH93 0076 2011 6238 5295 7
// -> 0076 2011 6238 5295 7 CH93
$canonicalized = substr($canonicalized, 4).substr($canonicalized, 0, 4);
// Convert all remaining letters to their ordinals
// The result is an integer, which is too large for PHP's int
// data type, so we store it in a string instead.
// e.g. 0076 2011 6238 5295 7 CH93
// -> 0076 2011 6238 5295 7 121893
$checkSum = self::toBigInt($canonicalized);
// Do a modulo-97 operation on the large integer
// We cannot use PHP's modulo operator, so we calculate the
// modulo step-wisely instead
if (1 !== self::bigModulo97($checkSum)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Iban::CHECKSUM_FAILED_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Iban::CHECKSUM_FAILED_ERROR)
->addViolation();
}
}
}
private static function toBigInt($string)
{
$chars = str_split($string);
$bigInt = '';
foreach ($chars as $char) {
// Convert uppercase characters to ordinals, starting with 10 for "A"
if (ctype_upper($char)) {
$bigInt .= (ord($char) - 55);
continue;
}
// Simply append digits
$bigInt .= $char;
}
return $bigInt;
}
private static function bigModulo97($bigInt)
{
$parts = str_split($bigInt, 7);
$rest = 0;
foreach ($parts as $part) {
$rest = ($rest.$part) % 97;
}
return $rest;
}
}

View file

@ -0,0 +1,23 @@
<?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\Constraints;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Daniel Holmes <daniel@danielholmes.org>
*/
class IdenticalTo extends AbstractComparison
{
public $message = 'This value should be identical to {{ compared_value_type }} {{ compared_value }}.';
}

View file

@ -0,0 +1,28 @@
<?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\Constraints;
/**
* Validates values are identical (===).
*
* @author Daniel Holmes <daniel@danielholmes.org>
*/
class IdenticalToValidator extends AbstractComparisonValidator
{
/**
* {@inheritdoc}
*/
protected function compareValues($value1, $value2)
{
return $value1 === $value2;
}
}

View file

@ -0,0 +1,81 @@
<?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\Constraints;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Benjamin Dulau <benjamin.dulau@gmail.com>
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class Image extends File
{
// Don't reuse values used in File
const SIZE_NOT_DETECTED_ERROR = 10;
const TOO_WIDE_ERROR = 11;
const TOO_NARROW_ERROR = 12;
const TOO_HIGH_ERROR = 13;
const TOO_LOW_ERROR = 14;
const RATIO_TOO_BIG_ERROR = 15;
const RATIO_TOO_SMALL_ERROR = 16;
const SQUARE_NOT_ALLOWED_ERROR = 17;
const LANDSCAPE_NOT_ALLOWED_ERROR = 18;
const PORTRAIT_NOT_ALLOWED_ERROR = 19;
// Include the mapping from the base class
protected static $errorNames = array(
self::NOT_FOUND_ERROR => 'NOT_FOUND_ERROR',
self::NOT_READABLE_ERROR => 'NOT_READABLE_ERROR',
self::EMPTY_ERROR => 'EMPTY_ERROR',
self::TOO_LARGE_ERROR => 'TOO_LARGE_ERROR',
self::INVALID_MIME_TYPE_ERROR => 'INVALID_MIME_TYPE_ERROR',
self::SIZE_NOT_DETECTED_ERROR => 'SIZE_NOT_DETECTED_ERROR',
self::TOO_WIDE_ERROR => 'TOO_WIDE_ERROR',
self::TOO_NARROW_ERROR => 'TOO_NARROW_ERROR',
self::TOO_HIGH_ERROR => 'TOO_HIGH_ERROR',
self::TOO_LOW_ERROR => 'TOO_LOW_ERROR',
self::RATIO_TOO_BIG_ERROR => 'RATIO_TOO_BIG_ERROR',
self::RATIO_TOO_SMALL_ERROR => 'RATIO_TOO_SMALL_ERROR',
self::SQUARE_NOT_ALLOWED_ERROR => 'SQUARE_NOT_ALLOWED_ERROR',
self::LANDSCAPE_NOT_ALLOWED_ERROR => 'LANDSCAPE_NOT_ALLOWED_ERROR',
self::PORTRAIT_NOT_ALLOWED_ERROR => 'PORTRAIT_NOT_ALLOWED_ERROR',
);
public $mimeTypes = 'image/*';
public $minWidth;
public $maxWidth;
public $maxHeight;
public $minHeight;
public $maxRatio;
public $minRatio;
public $allowSquare = true;
public $allowLandscape = true;
public $allowPortrait = true;
// The constant for a wrong MIME type is taken from the parent class.
public $mimeTypesMessage = 'This file is not a valid image.';
public $sizeNotDetectedMessage = 'The size of the image could not be detected.';
public $maxWidthMessage = 'The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.';
public $minWidthMessage = 'The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.';
public $maxHeightMessage = 'The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.';
public $minHeightMessage = 'The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.';
public $maxRatioMessage = 'The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.';
public $minRatioMessage = 'The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.';
public $allowSquareMessage = 'The image is square ({{ width }}x{{ height }}px). Square images are not allowed.';
public $allowLandscapeMessage = 'The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.';
public $allowPortraitMessage = 'The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.';
}

View file

@ -0,0 +1,261 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* Validates whether a value is a valid image file and is valid
* against minWidth, maxWidth, minHeight and maxHeight constraints.
*
* @author Benjamin Dulau <benjamin.dulau@gmail.com>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class ImageValidator extends FileValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Image) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Image');
}
$violations = count($this->context->getViolations());
parent::validate($value, $constraint);
$failed = count($this->context->getViolations()) !== $violations;
if ($failed || null === $value || '' === $value) {
return;
}
if (null === $constraint->minWidth && null === $constraint->maxWidth
&& null === $constraint->minHeight && null === $constraint->maxHeight
&& null === $constraint->minRatio && null === $constraint->maxRatio
&& $constraint->allowSquare && $constraint->allowLandscape && $constraint->allowPortrait) {
return;
}
$size = @getimagesize($value);
if (empty($size) || ($size[0] === 0) || ($size[1] === 0)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->sizeNotDetectedMessage)
->setCode(Image::SIZE_NOT_DETECTED_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->sizeNotDetectedMessage)
->setCode(Image::SIZE_NOT_DETECTED_ERROR)
->addViolation();
}
return;
}
$width = $size[0];
$height = $size[1];
if ($constraint->minWidth) {
if (!ctype_digit((string) $constraint->minWidth)) {
throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum width', $constraint->minWidth));
}
if ($width < $constraint->minWidth) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->minWidthMessage)
->setParameter('{{ width }}', $width)
->setParameter('{{ min_width }}', $constraint->minWidth)
->setCode(Image::TOO_NARROW_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->minWidthMessage)
->setParameter('{{ width }}', $width)
->setParameter('{{ min_width }}', $constraint->minWidth)
->setCode(Image::TOO_NARROW_ERROR)
->addViolation();
}
return;
}
}
if ($constraint->maxWidth) {
if (!ctype_digit((string) $constraint->maxWidth)) {
throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum width', $constraint->maxWidth));
}
if ($width > $constraint->maxWidth) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->maxWidthMessage)
->setParameter('{{ width }}', $width)
->setParameter('{{ max_width }}', $constraint->maxWidth)
->setCode(Image::TOO_WIDE_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->maxWidthMessage)
->setParameter('{{ width }}', $width)
->setParameter('{{ max_width }}', $constraint->maxWidth)
->setCode(Image::TOO_WIDE_ERROR)
->addViolation();
}
return;
}
}
if ($constraint->minHeight) {
if (!ctype_digit((string) $constraint->minHeight)) {
throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum height', $constraint->minHeight));
}
if ($height < $constraint->minHeight) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->minHeightMessage)
->setParameter('{{ height }}', $height)
->setParameter('{{ min_height }}', $constraint->minHeight)
->setCode(Image::TOO_LOW_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->minHeightMessage)
->setParameter('{{ height }}', $height)
->setParameter('{{ min_height }}', $constraint->minHeight)
->setCode(Image::TOO_LOW_ERROR)
->addViolation();
}
return;
}
}
if ($constraint->maxHeight) {
if (!ctype_digit((string) $constraint->maxHeight)) {
throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum height', $constraint->maxHeight));
}
if ($height > $constraint->maxHeight) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->maxHeightMessage)
->setParameter('{{ height }}', $height)
->setParameter('{{ max_height }}', $constraint->maxHeight)
->setCode(Image::TOO_HIGH_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->maxHeightMessage)
->setParameter('{{ height }}', $height)
->setParameter('{{ max_height }}', $constraint->maxHeight)
->setCode(Image::TOO_HIGH_ERROR)
->addViolation();
}
}
}
$ratio = round($width / $height, 2);
if (null !== $constraint->minRatio) {
if (!is_numeric((string) $constraint->minRatio)) {
throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum ratio', $constraint->minRatio));
}
if ($ratio < $constraint->minRatio) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->minRatioMessage)
->setParameter('{{ ratio }}', $ratio)
->setParameter('{{ min_ratio }}', $constraint->minRatio)
->setCode(Image::RATIO_TOO_SMALL_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->minRatioMessage)
->setParameter('{{ ratio }}', $ratio)
->setParameter('{{ min_ratio }}', $constraint->minRatio)
->setCode(Image::RATIO_TOO_SMALL_ERROR)
->addViolation();
}
}
}
if (null !== $constraint->maxRatio) {
if (!is_numeric((string) $constraint->maxRatio)) {
throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum ratio', $constraint->maxRatio));
}
if ($ratio > $constraint->maxRatio) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->maxRatioMessage)
->setParameter('{{ ratio }}', $ratio)
->setParameter('{{ max_ratio }}', $constraint->maxRatio)
->setCode(Image::RATIO_TOO_BIG_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->maxRatioMessage)
->setParameter('{{ ratio }}', $ratio)
->setParameter('{{ max_ratio }}', $constraint->maxRatio)
->setCode(Image::RATIO_TOO_BIG_ERROR)
->addViolation();
}
}
}
if (!$constraint->allowSquare && $width == $height) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->allowSquareMessage)
->setParameter('{{ width }}', $width)
->setParameter('{{ height }}', $height)
->setCode(Image::SQUARE_NOT_ALLOWED_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->allowSquareMessage)
->setParameter('{{ width }}', $width)
->setParameter('{{ height }}', $height)
->setCode(Image::SQUARE_NOT_ALLOWED_ERROR)
->addViolation();
}
}
if (!$constraint->allowLandscape && $width > $height) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->allowLandscapeMessage)
->setParameter('{{ width }}', $width)
->setParameter('{{ height }}', $height)
->setCode(Image::LANDSCAPE_NOT_ALLOWED_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->allowLandscapeMessage)
->setParameter('{{ width }}', $width)
->setParameter('{{ height }}', $height)
->setCode(Image::LANDSCAPE_NOT_ALLOWED_ERROR)
->addViolation();
}
}
if (!$constraint->allowPortrait && $width < $height) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->allowPortraitMessage)
->setParameter('{{ width }}', $width)
->setParameter('{{ height }}', $height)
->setCode(Image::PORTRAIT_NOT_ALLOWED_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->allowPortraitMessage)
->setParameter('{{ width }}', $width)
->setParameter('{{ height }}', $height)
->setCode(Image::PORTRAIT_NOT_ALLOWED_ERROR)
->addViolation();
}
}
}
}

View file

@ -0,0 +1,82 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
/**
* Validates that a value is a valid IP address.
*
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
* @author Joseph Bielawski <stloyd@gmail.com>
*
* @api
*/
class Ip extends Constraint
{
const V4 = '4';
const V6 = '6';
const ALL = 'all';
// adds FILTER_FLAG_NO_PRIV_RANGE flag (skip private ranges)
const V4_NO_PRIV = '4_no_priv';
const V6_NO_PRIV = '6_no_priv';
const ALL_NO_PRIV = 'all_no_priv';
// adds FILTER_FLAG_NO_RES_RANGE flag (skip reserved ranges)
const V4_NO_RES = '4_no_res';
const V6_NO_RES = '6_no_res';
const ALL_NO_RES = 'all_no_res';
// adds FILTER_FLAG_NO_PRIV_RANGE and FILTER_FLAG_NO_RES_RANGE flags (skip both)
const V4_ONLY_PUBLIC = '4_public';
const V6_ONLY_PUBLIC = '6_public';
const ALL_ONLY_PUBLIC = 'all_public';
protected static $versions = array(
self::V4,
self::V6,
self::ALL,
self::V4_NO_PRIV,
self::V6_NO_PRIV,
self::ALL_NO_PRIV,
self::V4_NO_RES,
self::V6_NO_RES,
self::ALL_NO_RES,
self::V4_ONLY_PUBLIC,
self::V6_ONLY_PUBLIC,
self::ALL_ONLY_PUBLIC,
);
public $version = self::V4;
public $message = 'This is not a valid IP address.';
/**
* {@inheritdoc}
*/
public function __construct($options = null)
{
parent::__construct($options);
if (!in_array($this->version, self::$versions)) {
throw new ConstraintDefinitionException(sprintf('The option "version" must be one of "%s"', implode('", "', self::$versions)));
}
}
}

View file

@ -0,0 +1,110 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* Validates whether a value is a valid IP address.
*
* @author Bernhard Schussek <bschussek@gmail.com>
* @author Joseph Bielawski <stloyd@gmail.com>
*
* @api
*/
class IpValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Ip) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Ip');
}
if (null === $value || '' === $value) {
return;
}
if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedTypeException($value, 'string');
}
$value = (string) $value;
switch ($constraint->version) {
case Ip::V4:
$flag = FILTER_FLAG_IPV4;
break;
case Ip::V6:
$flag = FILTER_FLAG_IPV6;
break;
case Ip::V4_NO_PRIV:
$flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE;
break;
case Ip::V6_NO_PRIV:
$flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE;
break;
case Ip::ALL_NO_PRIV:
$flag = FILTER_FLAG_NO_PRIV_RANGE;
break;
case Ip::V4_NO_RES:
$flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_RES_RANGE;
break;
case Ip::V6_NO_RES:
$flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE;
break;
case Ip::ALL_NO_RES:
$flag = FILTER_FLAG_NO_RES_RANGE;
break;
case Ip::V4_ONLY_PUBLIC:
$flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
break;
case Ip::V6_ONLY_PUBLIC:
$flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
break;
case Ip::ALL_ONLY_PUBLIC:
$flag = FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
break;
default:
$flag = null;
break;
}
if (!filter_var($value, FILTER_VALIDATE_IP, $flag)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}
}

View file

@ -0,0 +1,27 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class IsFalse extends Constraint
{
public $message = 'This value should be false.';
}

View file

@ -0,0 +1,49 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class IsFalseValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof IsFalse) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\IsFalse');
}
if (null === $value || false === $value || 0 === $value || '0' === $value) {
return;
}
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}

View file

@ -0,0 +1,27 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class IsNull extends Constraint
{
public $message = 'This value should be null.';
}

View file

@ -0,0 +1,47 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class IsNullValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof IsNull) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\IsNull');
}
if (null !== $value) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}
}

View file

@ -0,0 +1,27 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class IsTrue extends Constraint
{
public $message = 'This value should be true.';
}

View file

@ -0,0 +1,51 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class IsTrueValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof IsTrue) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\IsTrue');
}
if (null === $value) {
return;
}
if (true !== $value && 1 !== $value && '1' !== $value) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}
}

View file

@ -0,0 +1,67 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author The Whole Life To Learn <thewholelifetolearn@gmail.com>
* @author Manuel Reinhard <manu@sprain.ch>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class Isbn extends Constraint
{
const TOO_SHORT_ERROR = 1;
const TOO_LONG_ERROR = 2;
const INVALID_CHARACTERS_ERROR = 3;
const CHECKSUM_FAILED_ERROR = 4;
const TYPE_NOT_RECOGNIZED_ERROR = 5;
protected static $errorNames = array(
self::TOO_SHORT_ERROR => 'TOO_SHORT_ERROR',
self::TOO_LONG_ERROR => 'TOO_LONG_ERROR',
self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR',
self::CHECKSUM_FAILED_ERROR => 'CHECKSUM_FAILED_ERROR',
self::TYPE_NOT_RECOGNIZED_ERROR => 'TYPE_NOT_RECOGNIZED_ERROR',
);
public $isbn10Message = 'This value is not a valid ISBN-10.';
public $isbn13Message = 'This value is not a valid ISBN-13.';
public $bothIsbnMessage = 'This value is neither a valid ISBN-10 nor a valid ISBN-13.';
public $type;
public $message;
/**
* @deprecated since version 2.5, to be removed in 3.0. Use option "type" instead.
*
* @var bool
*/
public $isbn10 = false;
/**
* @deprecated since version 2.5, to be removed in 3.0. Use option "type" instead.
*
* @var bool
*/
public $isbn13 = false;
/**
* {@inheritdoc}
*/
public function getDefaultOption()
{
return 'type';
}
}

View file

@ -0,0 +1,216 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* Validates whether the value is a valid ISBN-10 or ISBN-13.
*
* @author The Whole Life To Learn <thewholelifetolearn@gmail.com>
* @author Manuel Reinhard <manu@sprain.ch>
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @see https://en.wikipedia.org/wiki/Isbn
*/
class IsbnValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Isbn) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Isbn');
}
if (null === $value || '' === $value) {
return;
}
if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedTypeException($value, 'string');
}
$value = (string) $value;
$canonical = str_replace('-', '', $value);
if (null === $constraint->type) {
if ($constraint->isbn10 && !$constraint->isbn13) {
@trigger_error('The "isbn10" option of the Isbn constraint is deprecated since version 2.5 and will be removed in 3.0. Use the "type" option instead.', E_USER_DEPRECATED);
$constraint->type = 'isbn10';
} elseif ($constraint->isbn13 && !$constraint->isbn10) {
@trigger_error('The "isbn13" option of the Isbn constraint is deprecated since version 2.5 and will be removed in 3.0. Use the "type" option instead.', E_USER_DEPRECATED);
$constraint->type = 'isbn13';
}
}
// Explicitly validate against ISBN-10
if ('isbn10' === $constraint->type) {
if (true !== ($code = $this->validateIsbn10($canonical))) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($this->getMessage($constraint, $constraint->type))
->setParameter('{{ value }}', $this->formatValue($value))
->setCode($code)
->addViolation();
} else {
$this->buildViolation($this->getMessage($constraint, $constraint->type))
->setParameter('{{ value }}', $this->formatValue($value))
->setCode($code)
->addViolation();
}
}
return;
}
// Explicitly validate against ISBN-13
if ('isbn13' === $constraint->type) {
if (true !== ($code = $this->validateIsbn13($canonical))) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($this->getMessage($constraint, $constraint->type))
->setParameter('{{ value }}', $this->formatValue($value))
->setCode($code)
->addViolation();
} else {
$this->buildViolation($this->getMessage($constraint, $constraint->type))
->setParameter('{{ value }}', $this->formatValue($value))
->setCode($code)
->addViolation();
}
}
return;
}
// Try both ISBNs
// First, try ISBN-10
$code = $this->validateIsbn10($canonical);
// The ISBN can only be an ISBN-13 if the value was too long for ISBN-10
if (Isbn::TOO_LONG_ERROR === $code) {
// Try ISBN-13 now
$code = $this->validateIsbn13($canonical);
// If too short, this means we have 11 or 12 digits
if (Isbn::TOO_SHORT_ERROR === $code) {
$code = Isbn::TYPE_NOT_RECOGNIZED_ERROR;
}
}
if (true !== $code) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($this->getMessage($constraint))
->setParameter('{{ value }}', $this->formatValue($value))
->setCode($code)
->addViolation();
} else {
$this->buildViolation($this->getMessage($constraint))
->setParameter('{{ value }}', $this->formatValue($value))
->setCode($code)
->addViolation();
}
}
}
protected function validateIsbn10($isbn)
{
// Choose an algorithm so that ERROR_INVALID_CHARACTERS is preferred
// over ERROR_TOO_SHORT/ERROR_TOO_LONG
// Otherwise "0-45122-5244" passes, but "0-45122_5244" reports
// "too long"
// Error priority:
// 1. ERROR_INVALID_CHARACTERS
// 2. ERROR_TOO_SHORT/ERROR_TOO_LONG
// 3. ERROR_CHECKSUM_FAILED
$checkSum = 0;
for ($i = 0; $i < 10; ++$i) {
// If we test the length before the loop, we get an ERROR_TOO_SHORT
// when actually an ERROR_INVALID_CHARACTERS is wanted, e.g. for
// "0-45122_5244" (typo)
if (!isset($isbn{$i})) {
return Isbn::TOO_SHORT_ERROR;
}
if ('X' === $isbn{$i}) {
$digit = 10;
} elseif (ctype_digit($isbn{$i})) {
$digit = $isbn{$i};
} else {
return Isbn::INVALID_CHARACTERS_ERROR;
}
$checkSum += $digit * (10 - $i);
}
if (isset($isbn{$i})) {
return Isbn::TOO_LONG_ERROR;
}
return 0 === $checkSum % 11 ? true : Isbn::CHECKSUM_FAILED_ERROR;
}
protected function validateIsbn13($isbn)
{
// Error priority:
// 1. ERROR_INVALID_CHARACTERS
// 2. ERROR_TOO_SHORT/ERROR_TOO_LONG
// 3. ERROR_CHECKSUM_FAILED
if (!ctype_digit($isbn)) {
return Isbn::INVALID_CHARACTERS_ERROR;
}
$length = strlen($isbn);
if ($length < 13) {
return Isbn::TOO_SHORT_ERROR;
}
if ($length > 13) {
return Isbn::TOO_LONG_ERROR;
}
$checkSum = 0;
for ($i = 0; $i < 13; $i += 2) {
$checkSum += $isbn{$i};
}
for ($i = 1; $i < 12; $i += 2) {
$checkSum += $isbn{$i}
* 3;
}
return 0 === $checkSum % 10 ? true : Isbn::CHECKSUM_FAILED_ERROR;
}
protected function getMessage($constraint, $type = null)
{
if (null !== $constraint->message) {
return $constraint->message;
} elseif ('isbn10' === $type) {
return $constraint->isbn10Message;
} elseif ('isbn13' === $type) {
return $constraint->isbn13Message;
}
return $constraint->bothIsbnMessage;
}
}

View file

@ -0,0 +1,44 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Antonio J. García Lagar <aj@garcialagar.es>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class Issn extends Constraint
{
const TOO_SHORT_ERROR = 1;
const TOO_LONG_ERROR = 2;
const MISSING_HYPHEN_ERROR = 3;
const INVALID_CHARACTERS_ERROR = 4;
const INVALID_CASE_ERROR = 5;
const CHECKSUM_FAILED_ERROR = 6;
protected static $errorNames = array(
self::TOO_SHORT_ERROR => 'TOO_SHORT_ERROR',
self::TOO_LONG_ERROR => 'TOO_LONG_ERROR',
self::MISSING_HYPHEN_ERROR => 'MISSING_HYPHEN_ERROR',
self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR',
self::INVALID_CASE_ERROR => 'INVALID_CASE_ERROR',
self::CHECKSUM_FAILED_ERROR => 'CHECKSUM_FAILED_ERROR',
);
public $message = 'This value is not a valid ISSN.';
public $caseSensitive = false;
public $requireHyphen = false;
}

View file

@ -0,0 +1,183 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* Validates whether the value is a valid ISSN.
*
* @author Antonio J. García Lagar <aj@garcialagar.es>
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @see https://en.wikipedia.org/wiki/Issn
*/
class IssnValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Issn) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Issn');
}
if (null === $value || '' === $value) {
return;
}
if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedTypeException($value, 'string');
}
$value = (string) $value;
$canonical = $value;
// 1234-567X
// ^
if (isset($canonical{4}) && '-' === $canonical{4}) {
// remove hyphen
$canonical = substr($canonical, 0, 4).substr($canonical, 5);
} elseif ($constraint->requireHyphen) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Issn::MISSING_HYPHEN_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Issn::MISSING_HYPHEN_ERROR)
->addViolation();
}
return;
}
$length = strlen($canonical);
if ($length < 8) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Issn::TOO_SHORT_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Issn::TOO_SHORT_ERROR)
->addViolation();
}
return;
}
if ($length > 8) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Issn::TOO_LONG_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Issn::TOO_LONG_ERROR)
->addViolation();
}
return;
}
// 1234567X
// ^^^^^^^ digits only
if (!ctype_digit(substr($canonical, 0, 7))) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Issn::INVALID_CHARACTERS_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Issn::INVALID_CHARACTERS_ERROR)
->addViolation();
}
return;
}
// 1234567X
// ^ digit, x or X
if (!ctype_digit($canonical{7}) && 'x' !== $canonical{7} && 'X' !== $canonical{7}) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Issn::INVALID_CHARACTERS_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Issn::INVALID_CHARACTERS_ERROR)
->addViolation();
}
return;
}
// 1234567X
// ^ case-sensitive?
if ($constraint->caseSensitive && 'x' === $canonical{7}) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Issn::INVALID_CASE_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Issn::INVALID_CASE_ERROR)
->addViolation();
}
return;
}
// Calculate a checksum. "X" equals 10.
$checkSum = 'X' === $canonical{7}
|| 'x' === $canonical{7}
? 10
: $canonical{7};
for ($i = 0; $i < 7; ++$i) {
// Multiply the first digit by 8, the second by 7, etc.
$checkSum += (8 - $i) * $canonical{$i};
}
if (0 !== $checkSum % 11) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Issn::CHECKSUM_FAILED_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Issn::CHECKSUM_FAILED_ERROR)
->addViolation();
}
}
}
}

View file

@ -0,0 +1,27 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class Language extends Constraint
{
public $message = 'This value is not a valid language.';
}

View file

@ -0,0 +1,61 @@
<?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\Constraints;
use Symfony\Component\Intl\Intl;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* Validates whether a value is a valid language code.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class LanguageValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Language) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Language');
}
if (null === $value || '' === $value) {
return;
}
if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedTypeException($value, 'string');
}
$value = (string) $value;
$languages = Intl::getLanguageBundle()->getLanguageNames();
if (!isset($languages[$value])) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}
}

View file

@ -0,0 +1,58 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\MissingOptionsException;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class Length extends Constraint
{
const TOO_SHORT_ERROR = 1;
const TOO_LONG_ERROR = 2;
protected static $errorNames = array(
self::TOO_SHORT_ERROR => 'TOO_SHORT_ERROR',
self::TOO_LONG_ERROR => 'TOO_LONG_ERROR',
);
public $maxMessage = 'This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.';
public $minMessage = 'This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.';
public $exactMessage = 'This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.';
public $charsetMessage = 'This value does not match the expected {{ charset }} charset.';
public $max;
public $min;
public $charset = 'UTF-8';
public function __construct($options = null)
{
if (null !== $options && !is_array($options)) {
$options = array(
'min' => $options,
'max' => $options,
);
}
parent::__construct($options);
if (null === $this->min && null === $this->max) {
throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max'));
}
}
}

View file

@ -0,0 +1,129 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class LengthValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Length) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Length');
}
if (null === $value || '' === $value) {
return;
}
if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedTypeException($value, 'string');
}
$stringValue = (string) $value;
$invalidCharset = false;
if ('UTF8' === $charset = strtoupper($constraint->charset)) {
$charset = 'UTF-8';
}
if ('UTF-8' === $charset) {
if (!preg_match('//u', $stringValue)) {
$invalidCharset = true;
} elseif (function_exists('utf8_decode')) {
$length = strlen(utf8_decode($stringValue));
} else {
preg_replace('/./u', '', $stringValue, -1, $length);
}
} elseif (function_exists('mb_strlen')) {
if (@mb_check_encoding($stringValue, $constraint->charset)) {
$length = mb_strlen($stringValue, $constraint->charset);
} else {
$invalidCharset = true;
}
} elseif (function_exists('iconv_strlen')) {
$length = @iconv_strlen($stringValue, $constraint->charset);
$invalidCharset = false === $length;
} else {
$length = strlen($stringValue);
}
if ($invalidCharset) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->charsetMessage)
->setParameter('{{ value }}', $this->formatValue($stringValue))
->setParameter('{{ charset }}', $constraint->charset)
->setInvalidValue($value)
->addViolation();
} else {
$this->buildViolation($constraint->charsetMessage)
->setParameter('{{ value }}', $this->formatValue($stringValue))
->setParameter('{{ charset }}', $constraint->charset)
->setInvalidValue($value)
->addViolation();
}
return;
}
if (null !== $constraint->max && $length > $constraint->max) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->maxMessage)
->setParameter('{{ value }}', $this->formatValue($stringValue))
->setParameter('{{ limit }}', $constraint->max)
->setInvalidValue($value)
->setPlural((int) $constraint->max)
->setCode(Length::TOO_LONG_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->maxMessage)
->setParameter('{{ value }}', $this->formatValue($stringValue))
->setParameter('{{ limit }}', $constraint->max)
->setInvalidValue($value)
->setPlural((int) $constraint->max)
->setCode(Length::TOO_LONG_ERROR)
->addViolation();
}
return;
}
if (null !== $constraint->min && $length < $constraint->min) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->minMessage)
->setParameter('{{ value }}', $this->formatValue($stringValue))
->setParameter('{{ limit }}', $constraint->min)
->setInvalidValue($value)
->setPlural((int) $constraint->min)
->setCode(Length::TOO_SHORT_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->minMessage)
->setParameter('{{ value }}', $this->formatValue($stringValue))
->setParameter('{{ limit }}', $constraint->min)
->setInvalidValue($value)
->setPlural((int) $constraint->min)
->setCode(Length::TOO_SHORT_ERROR)
->addViolation();
}
}
}
}

View file

@ -0,0 +1,23 @@
<?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\Constraints;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Daniel Holmes <daniel@danielholmes.org>
*/
class LessThan extends AbstractComparison
{
public $message = 'This value should be less than {{ compared_value }}.';
}

View file

@ -0,0 +1,23 @@
<?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\Constraints;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Daniel Holmes <daniel@danielholmes.org>
*/
class LessThanOrEqual extends AbstractComparison
{
public $message = 'This value should be less than or equal to {{ compared_value }}.';
}

View file

@ -0,0 +1,28 @@
<?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\Constraints;
/**
* Validates values are less than or equal to the previous (<=).
*
* @author Daniel Holmes <daniel@danielholmes.org>
*/
class LessThanOrEqualValidator extends AbstractComparisonValidator
{
/**
* {@inheritdoc}
*/
protected function compareValues($value1, $value2)
{
return $value1 <= $value2;
}
}

View file

@ -0,0 +1,28 @@
<?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\Constraints;
/**
* Validates values are less than the previous (<).
*
* @author Daniel Holmes <daniel@danielholmes.org>
*/
class LessThanValidator extends AbstractComparisonValidator
{
/**
* {@inheritdoc}
*/
protected function compareValues($value1, $value2)
{
return $value1 < $value2;
}
}

View file

@ -0,0 +1,27 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class Locale extends Constraint
{
public $message = 'This value is not a valid locale.';
}

View file

@ -0,0 +1,61 @@
<?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\Constraints;
use Symfony\Component\Intl\Intl;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* Validates whether a value is a valid locale code.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class LocaleValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Locale) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Locale');
}
if (null === $value || '' === $value) {
return;
}
if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedTypeException($value, 'string');
}
$value = (string) $value;
$locales = Intl::getLocaleBundle()->getLocaleNames();
if (!isset($locales[$value])) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}
}

View file

@ -0,0 +1,37 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* Metadata for the LuhnValidator.
*
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Tim Nagel <t.nagel@infinite.net.au>
* @author Greg Knapp http://gregk.me/2011/php-implementation-of-bank-card-luhn-algorithm/
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class Luhn extends Constraint
{
const INVALID_CHARACTERS_ERROR = 1;
const CHECKSUM_FAILED_ERROR = 2;
protected static $errorNames = array(
self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR',
self::CHECKSUM_FAILED_ERROR => 'CHECKSUM_FAILED_ERROR',
);
public $message = 'Invalid card number.';
}

View file

@ -0,0 +1,111 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* Validates a PAN using the LUHN Algorithm.
*
* For a list of example card numbers that are used to test this
* class, please see the LuhnValidatorTest class.
*
* @see http://en.wikipedia.org/wiki/Luhn_algorithm
*
* @author Tim Nagel <t.nagel@infinite.net.au>
* @author Greg Knapp http://gregk.me/2011/php-implementation-of-bank-card-luhn-algorithm/
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class LuhnValidator extends ConstraintValidator
{
/**
* Validates a credit card number with the Luhn algorithm.
*
* @param mixed $value
* @param Constraint $constraint
*
* @throws UnexpectedTypeException when the given credit card number is no string
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Luhn) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Luhn');
}
if (null === $value || '' === $value) {
return;
}
// Work with strings only, because long numbers are represented as floats
// internally and don't work with strlen()
if (!is_string($value) && !(is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedTypeException($value, 'string');
}
$value = (string) $value;
if (!ctype_digit($value)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Luhn::INVALID_CHARACTERS_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Luhn::INVALID_CHARACTERS_ERROR)
->addViolation();
}
return;
}
$checkSum = 0;
$length = strlen($value);
// Starting with the last digit and walking left, add every second
// digit to the check sum
// e.g. 7 9 9 2 7 3 9 8 7 1 3
// ^ ^ ^ ^ ^ ^
// = 7 + 9 + 7 + 9 + 7 + 3
for ($i = $length - 1; $i >= 0; $i -= 2) {
$checkSum += $value{$i};
}
// Starting with the second last digit and walking left, double every
// second digit and add it to the check sum
// For doubles greater than 9, sum the individual digits
// e.g. 7 9 9 2 7 3 9 8 7 1 3
// ^ ^ ^ ^ ^
// = 1+8 + 4 + 6 + 1+6 + 2
for ($i = $length - 2; $i >= 0; $i -= 2) {
$checkSum += array_sum(str_split($value{$i} * 2));
}
if (0 === $checkSum || 0 !== $checkSum % 10) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Luhn::CHECKSUM_FAILED_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Luhn::CHECKSUM_FAILED_ERROR)
->addViolation();
}
}
}
}

View file

@ -0,0 +1,27 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class NotBlank extends Constraint
{
public $message = 'This value should not be blank.';
}

View file

@ -0,0 +1,47 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class NotBlankValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof NotBlank) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\NotBlank');
}
if (false === $value || (empty($value) && '0' != $value)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}
}

View file

@ -0,0 +1,23 @@
<?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\Constraints;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Daniel Holmes <daniel@danielholmes.org>
*/
class NotEqualTo extends AbstractComparison
{
public $message = 'This value should not be equal to {{ compared_value }}.';
}

View file

@ -0,0 +1,28 @@
<?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\Constraints;
/**
* Validates values are all unequal (!=).
*
* @author Daniel Holmes <daniel@danielholmes.org>
*/
class NotEqualToValidator extends AbstractComparisonValidator
{
/**
* {@inheritdoc}
*/
protected function compareValues($value1, $value2)
{
return $value1 != $value2;
}
}

View file

@ -0,0 +1,23 @@
<?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\Constraints;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Daniel Holmes <daniel@danielholmes.org>
*/
class NotIdenticalTo extends AbstractComparison
{
public $message = 'This value should not be identical to {{ compared_value_type }} {{ compared_value }}.';
}

View file

@ -0,0 +1,28 @@
<?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\Constraints;
/**
* Validates values aren't identical (!==).
*
* @author Daniel Holmes <daniel@danielholmes.org>
*/
class NotIdenticalToValidator extends AbstractComparisonValidator
{
/**
* {@inheritdoc}
*/
protected function compareValues($value1, $value2)
{
return $value1 !== $value2;
}
}

View file

@ -0,0 +1,27 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class NotNull extends Constraint
{
public $message = 'This value should not be null.';
}

View file

@ -0,0 +1,38 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class NotNullValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof NotNull) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\NotNull');
}
if (null === $value) {
$this->context->addViolation($constraint->message);
}
}
}

View file

@ -0,0 +1,26 @@
<?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\Constraints;
@trigger_error('The '.__NAMESPACE__.'\Null class is deprecated since version 2.7 and will be removed in 3.0. Use the IsNull class in the same namespace instead.', E_USER_DEPRECATED);
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @deprecated since version 2.7, to be removed in 3.0. Use IsNull instead.
*/
class Null extends IsNull
{
}

View file

@ -0,0 +1,23 @@
<?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\Constraints;
@trigger_error('The '.__NAMESPACE__.'\NullValidator class is deprecated since version 2.7 and will be removed in 3.0. Use the IsNullValidator class in the same namespace instead.', E_USER_DEPRECATED);
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @deprecated since version 2.7, to be removed in 3.0. Use IsNullValidator instead.
*/
class NullValidator extends IsNullValidator
{
}

View file

@ -0,0 +1,22 @@
<?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\Constraints;
/**
* @Annotation
* @Target({"ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class Optional extends Existence
{
}

View file

@ -0,0 +1,51 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\MissingOptionsException;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class Range extends Constraint
{
const INVALID_VALUE_ERROR = 1;
const BEYOND_RANGE_ERROR = 2;
const BELOW_RANGE_ERROR = 3;
protected static $errorNames = array(
self::INVALID_VALUE_ERROR => 'INVALID_VALUE_ERROR',
self::BEYOND_RANGE_ERROR => 'BEYOND_RANGE_ERROR',
self::BELOW_RANGE_ERROR => 'BELOW_RANGE_ERROR',
);
public $minMessage = 'This value should be {{ limit }} or more.';
public $maxMessage = 'This value should be {{ limit }} or less.';
public $invalidMessage = 'This value should be a valid number.';
public $min;
public $max;
public function __construct($options = null)
{
parent::__construct($options);
if (null === $this->min && null === $this->max) {
throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max'));
}
}
}

View file

@ -0,0 +1,104 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class RangeValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Range) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Range');
}
if (null === $value) {
return;
}
if (!is_numeric($value) && !$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->invalidMessage)
->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE))
->setCode(Range::INVALID_VALUE_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->invalidMessage)
->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE))
->setCode(Range::INVALID_VALUE_ERROR)
->addViolation();
}
return;
}
$min = $constraint->min;
$max = $constraint->max;
// Convert strings to DateTimes if comparing another DateTime
// This allows to compare with any date/time value supported by
// the DateTime constructor:
// http://php.net/manual/en/datetime.formats.php
if ($value instanceof \DateTime || $value instanceof \DateTimeInterface) {
if (is_string($min)) {
$min = new \DateTime($min);
}
if (is_string($max)) {
$max = new \DateTime($max);
}
}
if (null !== $constraint->max && $value > $max) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->maxMessage)
->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE))
->setParameter('{{ limit }}', $this->formatValue($max, self::PRETTY_DATE))
->setCode(Range::BEYOND_RANGE_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->maxMessage)
->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE))
->setParameter('{{ limit }}', $this->formatValue($max, self::PRETTY_DATE))
->setCode(Range::BEYOND_RANGE_ERROR)
->addViolation();
}
return;
}
if (null !== $constraint->min && $value < $min) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->minMessage)
->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE))
->setParameter('{{ limit }}', $this->formatValue($min, self::PRETTY_DATE))
->setCode(Range::BELOW_RANGE_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->minMessage)
->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE))
->setParameter('{{ limit }}', $this->formatValue($min, self::PRETTY_DATE))
->setCode(Range::BELOW_RANGE_ERROR)
->addViolation();
}
}
}
}

View file

@ -0,0 +1,98 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class Regex extends Constraint
{
public $message = 'This value is not valid.';
public $pattern;
public $htmlPattern;
public $match = true;
/**
* {@inheritdoc}
*/
public function getDefaultOption()
{
return 'pattern';
}
/**
* {@inheritdoc}
*/
public function getRequiredOptions()
{
return array('pattern');
}
/**
* Converts the htmlPattern to a suitable format for HTML5 pattern.
* Example: /^[a-z]+$/ would be converted to [a-z]+
* However, if options are specified, it cannot be converted.
*
* Pattern is also ignored if match=false since the pattern should
* then be reversed before application.
*
* @link http://dev.w3.org/html5/spec/single-page.html#the-pattern-attribute
*
* @return string|null
*/
public function getHtmlPattern()
{
// If htmlPattern is specified, use it
if (null !== $this->htmlPattern) {
return empty($this->htmlPattern)
? null
: $this->htmlPattern;
}
// Quit if delimiters not at very beginning/end (e.g. when options are passed)
if ($this->pattern[0] !== $this->pattern[strlen($this->pattern) - 1]) {
return;
}
$delimiter = $this->pattern[0];
// Unescape the delimiter
$pattern = str_replace('\\'.$delimiter, $delimiter, substr($this->pattern, 1, -1));
// If the pattern is inverted, we can simply wrap it in
// ((?!pattern).)*
if (!$this->match) {
return '((?!'.$pattern.').)*';
}
// If the pattern contains an or statement, wrap the pattern in
// .*(pattern).* and quit. Otherwise we'd need to parse the pattern
if (false !== strpos($pattern, '|')) {
return '.*('.$pattern.').*';
}
// Trim leading ^, otherwise prepend .*
$pattern = '^' === $pattern[0] ? substr($pattern, 1) : '.*'.$pattern;
// Trim trailing $, otherwise append .*
$pattern = '$' === $pattern[strlen($pattern) - 1] ? substr($pattern, 0, -1) : $pattern.'.*';
return $pattern;
}
}

View file

@ -0,0 +1,60 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* Validates whether a value match or not given regexp pattern.
*
* @author Bernhard Schussek <bschussek@gmail.com>
* @author Joseph Bielawski <stloyd@gmail.com>
*
* @api
*/
class RegexValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Regex) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Regex');
}
if (null === $value || '' === $value) {
return;
}
if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedTypeException($value, 'string');
}
$value = (string) $value;
if ($constraint->match xor preg_match($constraint->pattern, $value)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}
}

View file

@ -0,0 +1,22 @@
<?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\Constraints;
/**
* @Annotation
* @Target({"ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class Required extends Existence
{
}

View file

@ -0,0 +1,35 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class Time extends Constraint
{
const INVALID_FORMAT_ERROR = 1;
const INVALID_TIME_ERROR = 2;
protected static $errorNames = array(
self::INVALID_FORMAT_ERROR => 'INVALID_FORMAT_ERROR',
self::INVALID_TIME_ERROR => 'INVALID_TIME_ERROR',
);
public $message = 'This value is not a valid time.';
}

View file

@ -0,0 +1,93 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class TimeValidator extends ConstraintValidator
{
const PATTERN = '/^(\d{2}):(\d{2}):(\d{2})$/';
/**
* Checks whether a time is valid.
*
* @param int $hour The hour
* @param int $minute The minute
* @param int $second The second
*
* @return bool Whether the time is valid
*
* @internal
*/
public static function checkTime($hour, $minute, $second)
{
return $hour >= 0 && $hour < 24 && $minute >= 0 && $minute < 60 && $second >= 0 && $second < 60;
}
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Time) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Time');
}
if (null === $value || '' === $value || $value instanceof \DateTime) {
return;
}
if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedTypeException($value, 'string');
}
$value = (string) $value;
if (!preg_match(static::PATTERN, $value, $matches)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Time::INVALID_FORMAT_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Time::INVALID_FORMAT_ERROR)
->addViolation();
}
return;
}
if (!self::checkTime($matches[1], $matches[2], $matches[3])) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Time::INVALID_TIME_ERROR)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Time::INVALID_TIME_ERROR)
->addViolation();
}
}
}
}

View file

@ -0,0 +1,55 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
/**
* @Annotation
*
* @since 2.5
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class Traverse extends Constraint
{
public $traverse = true;
public function __construct($options = null)
{
if (is_array($options) && array_key_exists('groups', $options)) {
throw new ConstraintDefinitionException(sprintf(
'The option "groups" is not supported by the constraint %s',
__CLASS__
));
}
parent::__construct($options);
}
/**
* {@inheritdoc}
*/
public function getDefaultOption()
{
return 'traverse';
}
/**
* {@inheritdoc}
*/
public function getTargets()
{
return self::CLASS_CONSTRAINT;
}
}

View file

@ -0,0 +1,26 @@
<?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\Constraints;
@trigger_error('The '.__NAMESPACE__.'\True class is deprecated since version 2.7 and will be removed in 3.0. Use the IsTrue class in the same namespace instead.', E_USER_DEPRECATED);
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @deprecated since version 2.7, to be removed in 3.0. Use IsTrue instead.
*/
class True extends IsTrue
{
}

View file

@ -0,0 +1,23 @@
<?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\Constraints;
@trigger_error('The '.__NAMESPACE__.'\TrueValidator class is deprecated since version 2.7 and will be removed in 3.0. Use the IsTrueValidator class in the same namespace instead.', E_USER_DEPRECATED);
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @deprecated since version 2.7, to be removed in 3.0. Use IsTrueValidator instead.
*/
class TrueValidator extends IsTrueValidator
{
}

View file

@ -0,0 +1,44 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class Type extends Constraint
{
public $message = 'This value should be of type {{ type }}.';
public $type;
/**
* {@inheritdoc}
*/
public function getDefaultOption()
{
return 'type';
}
/**
* {@inheritdoc}
*/
public function getRequiredOptions()
{
return array('type');
}
}

View file

@ -0,0 +1,64 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class TypeValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Type) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Type');
}
if (null === $value) {
return;
}
$type = strtolower($constraint->type);
$type = $type == 'boolean' ? 'bool' : $constraint->type;
$isFunction = 'is_'.$type;
$ctypeFunction = 'ctype_'.$type;
if (function_exists($isFunction) && $isFunction($value)) {
return;
} elseif (function_exists($ctypeFunction) && $ctypeFunction($value)) {
return;
} elseif ($value instanceof $constraint->type) {
return;
}
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setParameter('{{ type }}', $constraint->type)
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setParameter('{{ type }}', $constraint->type)
->addViolation();
}
}
}

View file

@ -0,0 +1,30 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class Url extends Constraint
{
public $message = 'This value is not a valid URL.';
public $dnsMessage = 'The host could not be resolved.';
public $protocols = array('http', 'https');
public $checkDNS = false;
}

View file

@ -0,0 +1,92 @@
<?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\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class UrlValidator extends ConstraintValidator
{
const PATTERN = '~^
(%s):// # protocol
(([\pL\pN-]+:)?([\pL\pN-]+)@)? # basic auth
(
([\pL\pN\pS-\.])+(\.?([\pL]|xn\-\-[\pL\pN-]+)+\.?) # a domain name
| # or
\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} # a IP address
| # or
\[
(?:(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-f]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,1}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,2}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,3}(?:(?:[0-9a-f]{1,4})))?::(?:(?:[0-9a-f]{1,4})):)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,4}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,5}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,6}(?:(?:[0-9a-f]{1,4})))?::))))
\] # a IPv6 address
)
(:[0-9]+)? # a port (optional)
(/?|/\S+) # a /, nothing or a / with something
$~ixu';
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Url) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Url');
}
if (null === $value || '' === $value) {
return;
}
if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedTypeException($value, 'string');
}
$value = (string) $value;
$pattern = sprintf(static::PATTERN, implode('|', $constraint->protocols));
if (!preg_match($pattern, $value)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
} else {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
return;
}
if ($constraint->checkDNS) {
$host = parse_url($value, PHP_URL_HOST);
if (!checkdnsrr($host, 'ANY')) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->dnsMessage)
->setParameter('{{ value }}', $this->formatValue($host))
->addViolation();
} else {
$this->buildViolation($constraint->dnsMessage)
->setParameter('{{ value }}', $this->formatValue($host))
->addViolation();
}
}
}
}
}

View file

@ -0,0 +1,77 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
*
* @author Colin O'Dell <colinodell@gmail.com>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class Uuid extends Constraint
{
const TOO_SHORT_ERROR = 1;
const TOO_LONG_ERROR = 2;
const INVALID_CHARACTERS_ERROR = 3;
const INVALID_HYPHEN_PLACEMENT_ERROR = 4;
const INVALID_VERSION_ERROR = 5;
const INVALID_VARIANT_ERROR = 6;
protected static $errorNames = array(
self::TOO_SHORT_ERROR => 'TOO_SHORT_ERROR',
self::TOO_LONG_ERROR => 'TOO_LONG_ERROR',
self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR',
self::INVALID_HYPHEN_PLACEMENT_ERROR => 'INVALID_HYPHEN_PLACEMENT_ERROR',
self::INVALID_VERSION_ERROR => 'INVALID_VERSION_ERROR',
self::INVALID_VARIANT_ERROR => 'INVALID_VARIANT_ERROR',
);
// Possible versions defined by RFC 4122
const V1_MAC = 1;
const V2_DCE = 2;
const V3_MD5 = 3;
const V4_RANDOM = 4;
const V5_SHA1 = 5;
/**
* Message to display when validation fails.
*
* @var string
*/
public $message = 'This is not a valid UUID.';
/**
* Strict mode only allows UUIDs that meet the formal definition and formatting per RFC 4122.
*
* Set this to `false` to allow legacy formats with different dash positioning or wrapping characters
*
* @var bool
*/
public $strict = true;
/**
* Array of allowed versions (see version constants above).
*
* All UUID versions are allowed by default
*
* @var int[]
*/
public $versions = array(
self::V1_MAC,
self::V2_DCE,
self::V3_MD5,
self::V4_RANDOM,
self::V5_SHA1,
);
}

Some files were not shown because too many files have changed in this diff Show more