Chris@14: Chris@14: * Chris@14: * For the full copyright and license information, please view the LICENSE Chris@14: * file that was distributed with this source code. Chris@14: */ Chris@14: Chris@14: namespace Symfony\Component\Validator\Validator; Chris@14: Chris@14: use Symfony\Component\Validator\Context\ExecutionContextInterface; Chris@14: Chris@14: /** Chris@14: * Collects some data about validator calls. Chris@14: * Chris@14: * @author Maxime Steinhausser Chris@14: */ Chris@14: class TraceableValidator implements ValidatorInterface Chris@14: { Chris@14: private $validator; Chris@17: private $collectedData = []; Chris@14: Chris@14: public function __construct(ValidatorInterface $validator) Chris@14: { Chris@14: $this->validator = $validator; Chris@14: } Chris@14: Chris@14: /** Chris@14: * @return array Chris@14: */ Chris@14: public function getCollectedData() Chris@14: { Chris@14: return $this->collectedData; Chris@14: } Chris@14: Chris@14: public function reset() Chris@14: { Chris@17: $this->collectedData = []; Chris@14: } Chris@14: Chris@14: /** Chris@14: * {@inheritdoc} Chris@14: */ Chris@14: public function getMetadataFor($value) Chris@14: { Chris@14: return $this->validator->getMetadataFor($value); Chris@14: } Chris@14: Chris@14: /** Chris@14: * {@inheritdoc} Chris@14: */ Chris@14: public function hasMetadataFor($value) Chris@14: { Chris@14: return $this->validator->hasMetadataFor($value); Chris@14: } Chris@14: Chris@14: /** Chris@14: * {@inheritdoc} Chris@14: */ Chris@14: public function validate($value, $constraints = null, $groups = null) Chris@14: { Chris@14: $violations = $this->validator->validate($value, $constraints, $groups); Chris@14: Chris@14: $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 7); Chris@14: Chris@14: $file = $trace[0]['file']; Chris@14: $line = $trace[0]['line']; Chris@14: Chris@14: for ($i = 1; $i < 7; ++$i) { Chris@14: if (isset($trace[$i]['class'], $trace[$i]['function']) Chris@14: && 'validate' === $trace[$i]['function'] Chris@14: && is_a($trace[$i]['class'], ValidatorInterface::class, true) Chris@14: ) { Chris@14: $file = $trace[$i]['file']; Chris@14: $line = $trace[$i]['line']; Chris@14: Chris@14: while (++$i < 7) { Chris@14: if (isset($trace[$i]['function'], $trace[$i]['file']) && empty($trace[$i]['class']) && 0 !== strpos($trace[$i]['function'], 'call_user_func')) { Chris@14: $file = $trace[$i]['file']; Chris@14: $line = $trace[$i]['line']; Chris@14: Chris@14: break; Chris@14: } Chris@14: } Chris@14: break; Chris@14: } Chris@14: } Chris@14: Chris@14: $name = str_replace('\\', '/', $file); Chris@14: $name = substr($name, strrpos($name, '/') + 1); Chris@14: Chris@17: $this->collectedData[] = [ Chris@14: 'caller' => compact('name', 'file', 'line'), Chris@14: 'context' => compact('value', 'constraints', 'groups'), Chris@14: 'violations' => iterator_to_array($violations), Chris@17: ]; Chris@14: Chris@14: return $violations; Chris@14: } Chris@14: Chris@14: /** Chris@14: * {@inheritdoc} Chris@14: */ Chris@14: public function validateProperty($object, $propertyName, $groups = null) Chris@14: { Chris@14: return $this->validator->validateProperty($object, $propertyName, $groups); Chris@14: } Chris@14: Chris@14: /** Chris@14: * {@inheritdoc} Chris@14: */ Chris@14: public function validatePropertyValue($objectOrClass, $propertyName, $value, $groups = null) Chris@14: { Chris@14: return $this->validator->validatePropertyValue($objectOrClass, $propertyName, $value, $groups); Chris@14: } Chris@14: Chris@14: /** Chris@14: * {@inheritdoc} Chris@14: */ Chris@14: public function startContext() Chris@14: { Chris@14: return $this->validator->startContext(); Chris@14: } Chris@14: Chris@14: /** Chris@14: * {@inheritdoc} Chris@14: */ Chris@14: public function inContext(ExecutionContextInterface $context) Chris@14: { Chris@14: return $this->validator->inContext($context); Chris@14: } Chris@14: }