* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Sonata\AdminBundle\Validator; use Symfony\Component\Validator\ConstraintValidatorFactoryInterface; use Symfony\Component\Validator\ExecutionContextInterface; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Validator\Constraint; class ErrorElement { /** * @var ExecutionContextInterface */ protected $context; /** * @var string */ protected $group; /** * @var ConstraintValidationFactoryInterface */ protected $constraintValidatorFactory; protected $stack = array(); protected $propertyPaths = array(); protected $subject; protected $current; protected $basePropertyPath; protected $errors = array(); /** * @param mixed $subject * @param ConstraintValidatorFactoryInterface $constraintValidatorFactory * @param ExecutionContextInterface $context * @param string $group */ public function __construct($subject, ConstraintValidatorFactoryInterface $constraintValidatorFactory, ExecutionContextInterface $context, $group) { $this->subject = $subject; $this->context = $context; $this->group = $group; $this->constraintValidatorFactory = $constraintValidatorFactory; $this->current = ''; $this->basePropertyPath = $this->context->getPropertyPath(); } /** * @throws \RunTimeException * * @param string $name * @param array $arguments * * @return ErrorElement */ public function __call($name, array $arguments = array()) { if (substr($name, 0, 6) == 'assert') { $this->validate($this->newConstraint(substr($name, 6), isset($arguments[0]) ? $arguments[0] : array())); } else { throw new \RunTimeException('Unable to recognize the command'); } return $this; } /** * @param Constraint $constraint * * @return ErrorElement */ public function addConstraint(Constraint $constraint) { $this->validate($constraint); return $this; } /** * @param string $name * @param bool $key * * @return ErrorElement */ public function with($name, $key = false) { $key = $key ? $name . '.' . $key : $name; $this->stack[] = $key; $this->current = implode('.', $this->stack); if (!isset($this->propertyPaths[$this->current])) { $this->propertyPaths[$this->current] = new PropertyPath($this->current); } return $this; } /** * @return ErrorElement */ public function end() { array_pop($this->stack); $this->current = implode('.', $this->stack); return $this; } /** * @param \Symfony\Component\Validator\Constraint $constraint * * @return void */ protected function validate(Constraint $constraint) { $subPath = (string) $this->getCurrentPropertyPath(); $this->context->validateValue($this->getValue(), $constraint, $subPath, $this->group); } /** * @return string */ public function getFullPropertyPath() { if ($this->getCurrentPropertyPath()) { return sprintf('%s.%s', $this->basePropertyPath, $this->getCurrentPropertyPath()); } else { return $this->basePropertyPath; } } /** * Return the value linked to * * @return mixed */ protected function getValue() { if ($this->current == '') { return $this->subject; } $propertyAccessor = PropertyAccess::createPropertyAccessor(); return $propertyAccessor->getValue($this->subject, $this->getCurrentPropertyPath()); } /** * @return mixed */ public function getSubject() { return $this->subject; } /** * @param string $name * @param array $options * * @return */ protected function newConstraint($name, array $options = array()) { if (strpos($name, '\\') !== false && class_exists($name)) { $className = (string) $name; } else { $className = 'Symfony\\Component\\Validator\\Constraints\\' . $name; } return new $className($options); } /** * @return null|PropertyPath */ protected function getCurrentPropertyPath() { if (!isset($this->propertyPaths[$this->current])) { return null; //global error } return $this->propertyPaths[$this->current]; } /** * @param string|array $message * @param array $parameters * @param null $value * * @return ErrorElement */ public function addViolation($message, $parameters = array(), $value = null) { if (is_array($message)) { $value = isset($message[2]) ? $message[2] : $value; $parameters = isset($message[1]) ? (array) $message[1] : array(); $message = isset($message[0]) ? $message[0] : 'error'; } $subPath = (string) $this->getCurrentPropertyPath(); $this->context->addViolationAt($subPath, $message, $parameters, $value); $this->errors[] = array($message, $parameters, $value); return $this; } /** * @return array */ public function getErrors() { return $this->errors; } }