ChoiceValidator.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Validator\Constraints;
  11. use Symfony\Component\Validator\Context\ExecutionContextInterface;
  12. use Symfony\Component\Validator\Constraint;
  13. use Symfony\Component\Validator\ConstraintValidator;
  14. use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
  15. use Symfony\Component\Validator\Exception\UnexpectedTypeException;
  16. /**
  17. * ChoiceValidator validates that the value is one of the expected values.
  18. *
  19. * @author Fabien Potencier <fabien@symfony.com>
  20. * @author Florian Eckerstorfer <florian@eckerstorfer.org>
  21. * @author Bernhard Schussek <bschussek@gmail.com>
  22. */
  23. class ChoiceValidator extends ConstraintValidator
  24. {
  25. /**
  26. * {@inheritdoc}
  27. */
  28. public function validate($value, Constraint $constraint)
  29. {
  30. if (!$constraint instanceof Choice) {
  31. throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Choice');
  32. }
  33. if (!is_array($constraint->choices) && !$constraint->callback) {
  34. throw new ConstraintDefinitionException('Either "choices" or "callback" must be specified on constraint Choice');
  35. }
  36. if (null === $value) {
  37. return;
  38. }
  39. if ($constraint->multiple && !is_array($value)) {
  40. throw new UnexpectedTypeException($value, 'array');
  41. }
  42. if ($constraint->callback) {
  43. if (!is_callable($choices = array($this->context->getClassName(), $constraint->callback))
  44. && !is_callable($choices = $constraint->callback)
  45. ) {
  46. throw new ConstraintDefinitionException('The Choice constraint expects a valid callback');
  47. }
  48. $choices = call_user_func($choices);
  49. } else {
  50. $choices = $constraint->choices;
  51. }
  52. if ($constraint->multiple) {
  53. foreach ($value as $_value) {
  54. if (!in_array($_value, $choices, $constraint->strict)) {
  55. if ($this->context instanceof ExecutionContextInterface) {
  56. $this->context->buildViolation($constraint->multipleMessage)
  57. ->setParameter('{{ value }}', $this->formatValue($_value))
  58. ->setCode(Choice::NO_SUCH_CHOICE_ERROR)
  59. ->setInvalidValue($_value)
  60. ->addViolation();
  61. } else {
  62. $this->buildViolation($constraint->multipleMessage)
  63. ->setParameter('{{ value }}', $this->formatValue($_value))
  64. ->setCode(Choice::NO_SUCH_CHOICE_ERROR)
  65. ->setInvalidValue($_value)
  66. ->addViolation();
  67. }
  68. return;
  69. }
  70. }
  71. $count = count($value);
  72. if ($constraint->min !== null && $count < $constraint->min) {
  73. if ($this->context instanceof ExecutionContextInterface) {
  74. $this->context->buildViolation($constraint->minMessage)
  75. ->setParameter('{{ limit }}', $constraint->min)
  76. ->setPlural((int) $constraint->min)
  77. ->setCode(Choice::TOO_FEW_ERROR)
  78. ->addViolation();
  79. } else {
  80. $this->buildViolation($constraint->minMessage)
  81. ->setParameter('{{ limit }}', $constraint->min)
  82. ->setPlural((int) $constraint->min)
  83. ->setCode(Choice::TOO_FEW_ERROR)
  84. ->addViolation();
  85. }
  86. return;
  87. }
  88. if ($constraint->max !== null && $count > $constraint->max) {
  89. if ($this->context instanceof ExecutionContextInterface) {
  90. $this->context->buildViolation($constraint->maxMessage)
  91. ->setParameter('{{ limit }}', $constraint->max)
  92. ->setPlural((int) $constraint->max)
  93. ->setCode(Choice::TOO_MANY_ERROR)
  94. ->addViolation();
  95. } else {
  96. $this->buildViolation($constraint->maxMessage)
  97. ->setParameter('{{ limit }}', $constraint->max)
  98. ->setPlural((int) $constraint->max)
  99. ->setCode(Choice::TOO_MANY_ERROR)
  100. ->addViolation();
  101. }
  102. return;
  103. }
  104. } elseif (!in_array($value, $choices, $constraint->strict)) {
  105. if ($this->context instanceof ExecutionContextInterface) {
  106. $this->context->buildViolation($constraint->message)
  107. ->setParameter('{{ value }}', $this->formatValue($value))
  108. ->setCode(Choice::NO_SUCH_CHOICE_ERROR)
  109. ->addViolation();
  110. } else {
  111. $this->buildViolation($constraint->message)
  112. ->setParameter('{{ value }}', $this->formatValue($value))
  113. ->setCode(Choice::NO_SUCH_CHOICE_ERROR)
  114. ->addViolation();
  115. }
  116. }
  117. }
  118. }