ExpressionValidator.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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\ExpressionLanguage\ExpressionLanguage;
  12. use Symfony\Component\PropertyAccess\PropertyAccess;
  13. use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
  14. use Symfony\Component\PropertyAccess\PropertyPath;
  15. use Symfony\Component\Validator\Constraint;
  16. use Symfony\Component\Validator\ConstraintValidator;
  17. use Symfony\Component\Validator\Context\ExecutionContextInterface;
  18. use Symfony\Component\Validator\Exception\RuntimeException;
  19. use Symfony\Component\Validator\Exception\UnexpectedTypeException;
  20. /**
  21. * @author Fabien Potencier <fabien@symfony.com>
  22. * @author Bernhard Schussek <bschussek@symfony.com>
  23. */
  24. class ExpressionValidator extends ConstraintValidator
  25. {
  26. private $propertyAccessor;
  27. private $expressionLanguage;
  28. public function __construct(PropertyAccessorInterface $propertyAccessor = null, ExpressionLanguage $expressionLanguage = null)
  29. {
  30. $this->propertyAccessor = $propertyAccessor;
  31. $this->expressionLanguage = $expressionLanguage;
  32. }
  33. /**
  34. * {@inheritdoc}
  35. */
  36. public function validate($value, Constraint $constraint)
  37. {
  38. if (!$constraint instanceof Expression) {
  39. throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Expression');
  40. }
  41. $variables = array();
  42. // Symfony 2.5+
  43. if ($this->context instanceof ExecutionContextInterface) {
  44. $variables['value'] = $value;
  45. $variables['this'] = $this->context->getObject();
  46. } elseif (null === $this->context->getPropertyName()) {
  47. $variables['value'] = $value;
  48. $variables['this'] = $value;
  49. } else {
  50. $root = $this->context->getRoot();
  51. $variables['value'] = $value;
  52. if (\is_object($root)) {
  53. // Extract the object that the property belongs to from the object
  54. // graph
  55. $path = new PropertyPath($this->context->getPropertyPath());
  56. $parentPath = $path->getParent();
  57. $variables['this'] = $parentPath ? $this->getPropertyAccessor()->getValue($root, $parentPath) : $root;
  58. } else {
  59. $variables['this'] = null;
  60. }
  61. }
  62. if (!$this->getExpressionLanguage()->evaluate($constraint->expression, $variables)) {
  63. if ($this->context instanceof ExecutionContextInterface) {
  64. $this->context->buildViolation($constraint->message)
  65. ->setParameter('{{ value }}', $this->formatValue($value, self::OBJECT_TO_STRING))
  66. ->setCode(Expression::EXPRESSION_FAILED_ERROR)
  67. ->addViolation();
  68. } else {
  69. $this->buildViolation($constraint->message)
  70. ->setParameter('{{ value }}', $this->formatValue($value, self::OBJECT_TO_STRING))
  71. ->setCode(Expression::EXPRESSION_FAILED_ERROR)
  72. ->addViolation();
  73. }
  74. }
  75. }
  76. private function getExpressionLanguage()
  77. {
  78. if (null === $this->expressionLanguage) {
  79. if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
  80. throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
  81. }
  82. $this->expressionLanguage = new ExpressionLanguage();
  83. }
  84. return $this->expressionLanguage;
  85. }
  86. private function getPropertyAccessor()
  87. {
  88. if (null === $this->propertyAccessor) {
  89. if (!class_exists('Symfony\Component\PropertyAccess\PropertyAccess')) {
  90. throw new RuntimeException('Unable to use expressions as the Symfony PropertyAccess component is not installed.');
  91. }
  92. $this->propertyAccessor = PropertyAccess::createPropertyAccessor();
  93. }
  94. return $this->propertyAccessor;
  95. }
  96. }