[Profiler][Validator] Add a validator panel in profiler
This commit is contained in:
parent
b223241f64
commit
ac5e884f36
@ -81,6 +81,7 @@ class FrameworkExtension extends Extension
|
||||
private $translationConfigEnabled = false;
|
||||
private $sessionConfigEnabled = false;
|
||||
private $annotationsConfigEnabled = false;
|
||||
private $validatorConfigEnabled = false;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
@ -456,6 +457,10 @@ class FrameworkExtension extends Extension
|
||||
$loader->load('form_debug.xml');
|
||||
}
|
||||
|
||||
if ($this->validatorConfigEnabled) {
|
||||
$loader->load('validator_debug.xml');
|
||||
}
|
||||
|
||||
if ($this->translationConfigEnabled) {
|
||||
$loader->load('translation_debug.xml');
|
||||
$container->getDefinition('translator.data_collector')->setDecoratedService('translator');
|
||||
@ -1107,7 +1112,7 @@ class FrameworkExtension extends Extension
|
||||
*/
|
||||
private function registerValidationConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
{
|
||||
if (!$this->isConfigEnabled($container, $config)) {
|
||||
if (!$this->validatorConfigEnabled = $this->isConfigEnabled($container, $config)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" ?>
|
||||
|
||||
<container xmlns="http://symfony.com/schema/dic/services"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||
|
||||
<services>
|
||||
<defaults public="false" />
|
||||
|
||||
<service id="debug.validator" decorates="validator" decoration-priority="255" class="Symfony\Component\Validator\Validator\TraceableValidator">
|
||||
<argument type="service" id="debug.validator.inner" />
|
||||
</service>
|
||||
|
||||
<!-- DataCollector -->
|
||||
<service id="data_collector.validator" class="Symfony\Component\Validator\DataCollector\ValidatorDataCollector">
|
||||
<argument type="service" id="debug.validator"/>
|
||||
<tag name="data_collector" template="@WebProfiler/Collector/validator.html.twig" id="validator" priority="320" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
@ -49,7 +49,7 @@
|
||||
"symfony/stopwatch": "~2.8|~3.0|~4.0",
|
||||
"symfony/translation": "~3.2|~4.0",
|
||||
"symfony/templating": "~2.8|~3.0|~4.0",
|
||||
"symfony/validator": "~3.3|~4.0",
|
||||
"symfony/validator": "~3.4|~4.0",
|
||||
"symfony/var-dumper": "~3.3|~4.0",
|
||||
"symfony/workflow": "~3.3|~4.0",
|
||||
"symfony/yaml": "~3.2|~4.0",
|
||||
@ -69,7 +69,7 @@
|
||||
"symfony/property-info": "<3.3",
|
||||
"symfony/serializer": "<3.3",
|
||||
"symfony/translation": "<3.2",
|
||||
"symfony/validator": "<3.3",
|
||||
"symfony/validator": "<3.4",
|
||||
"symfony/workflow": "<3.3"
|
||||
},
|
||||
"suggest": {
|
||||
|
@ -0,0 +1,98 @@
|
||||
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
|
||||
|
||||
{% block toolbar %}
|
||||
{% if collector.violationsCount > 0 or collector.calls|length %}
|
||||
{% set status_color = collector.violationsCount ? 'red' : '' %}
|
||||
{% set icon %}
|
||||
{{ include('@WebProfiler/Icon/validator.svg') }}
|
||||
<span class="sf-toolbar-value">
|
||||
{{ collector.violationsCount }}
|
||||
</span>
|
||||
{% endset %}
|
||||
|
||||
{% set text %}
|
||||
<div class="sf-toolbar-info-piece">
|
||||
<b>Validator calls</b>
|
||||
<span class="sf-toolbar-status">{{ collector.calls|length }}</span>
|
||||
</div>
|
||||
<div class="sf-toolbar-info-piece">
|
||||
<b>Number of violations</b>
|
||||
<span class="sf-toolbar-status {{- collector.violationsCount > 0 ? ' sf-toolbar-status-red' }}">{{ collector.violationsCount }}</span>
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
{{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url, status: status_color }) }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block menu %}
|
||||
<span class="label {{- collector.violationsCount ? ' label-status-error' }} {{ collector.calls is empty ? 'disabled' }}">
|
||||
<span class="icon">{{ include('@WebProfiler/Icon/validator.svg') }}</span>
|
||||
<strong>Validator</strong>
|
||||
{% if collector.violationsCount > 0 %}
|
||||
<span class="count">
|
||||
<span>{{ collector.violationsCount }}</span>
|
||||
</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
{% endblock %}
|
||||
|
||||
{% block panel %}
|
||||
<h2>Validator calls</h2>
|
||||
|
||||
{% for call in collector.calls %}
|
||||
<div class="sf-validator sf-reset">
|
||||
<span class="metadata">In
|
||||
{% set caller = call.caller %}
|
||||
{% if caller.line %}
|
||||
{% set link = caller.file|file_link(caller.line) %}
|
||||
{% if link %}
|
||||
<a href="{{ link }}" title="{{ caller.file }}">{{ caller.name }}</a>
|
||||
{% else %}
|
||||
<abbr title="{{ caller.file }}">{{ caller.name }}</abbr>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{ caller.name }}
|
||||
{% endif %}
|
||||
line <a class="text-small sf-toggle" data-toggle-selector="#sf-trace-{{ loop.index0 }}">{{ caller.line }}</a> (<a class="text-small sf-toggle" data-toggle-selector="#sf-context-{{ loop.index0 }}">context</a>):
|
||||
</span>
|
||||
|
||||
<div class="sf-validator-compact hidden" id="sf-trace-{{ loop.index0 }}">
|
||||
<div class="trace">
|
||||
{{ caller.file|file_excerpt(caller.line) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sf-validator-compact hidden sf-validator-context" id="sf-context-{{ loop.index0 }}">
|
||||
{{ profiler_dump(call.context, maxDepth=1) }}
|
||||
</div>
|
||||
|
||||
{% if call.violations|length %}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Path</th>
|
||||
<th>Message</th>
|
||||
<th>Invalid value</th>
|
||||
<th>Violation</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% for violation in call.violations %}
|
||||
<tr>
|
||||
<td>{{ violation.propertyPath }}</td>
|
||||
<td>{{ violation.message }}</td>
|
||||
<td>{{ profiler_dump(violation.seek('invalidValue')) }}</td>
|
||||
<td>{{ profiler_dump(violation) }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
No violations
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="empty">
|
||||
<p>No calls to the validator were collected during this request.</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="24" height="24" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve"><path fill="#aaaaaa" d="M19.54,22.5H4.29a2.88,2.88,0,0,1-2.87-2.87V4.37A2.88,2.88,0,0,1,4.29,1.5H18.54a1,1,0,0,1,0,2H4.29a.88.88,0,0,0-.87.87V19.63a.88.88,0,0,0,.87.87H19.54a.88.88,0,0,0,.87-.87V11.29a1,1,0,1,1,2,0v8.33A2.88,2.88,0,0,1,19.54,22.5ZM13,17.29,22.88,6a1.5,1.5,0,1,0-2.26-2L12,14,8,9.11A1.5,1.5,0,0,0,5.65,11l5.1,6.25a1.5,1.5,0,0,0,1.14.55h0A1.5,1.5,0,0,0,13,17.29Z"/></svg>
|
After Width: | Height: | Size: 541 B |
@ -880,6 +880,31 @@ table.logs .metadata {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
{# Validator panel
|
||||
========================================================================= #}
|
||||
|
||||
#collector-content .sf-validator {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
#collector-content .sf-validator .sf-validator-context,
|
||||
#collector-content .sf-validator .trace {
|
||||
border: 1px solid #DDD;
|
||||
background: #FFF;
|
||||
padding: 10px;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
#collector-content .sf-validator .trace {
|
||||
font-size: 12px;
|
||||
}
|
||||
#collector-content .sf-validator .trace li {
|
||||
margin-bottom: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#collector-content .sf-validator .trace li.selected {
|
||||
background: rgba(255, 255, 153, 0.5);
|
||||
}
|
||||
|
||||
{# Dump panel
|
||||
========================================================================= #}
|
||||
#collector-content .sf-dump {
|
||||
|
@ -0,0 +1,105 @@
|
||||
<?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\DataCollector;
|
||||
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
|
||||
use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
|
||||
use Symfony\Component\Validator\Validator\TraceableValidator;
|
||||
use Symfony\Component\VarDumper\Caster\Caster;
|
||||
use Symfony\Component\VarDumper\Caster\ClassStub;
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
|
||||
/**
|
||||
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
|
||||
*/
|
||||
class ValidatorDataCollector extends DataCollector implements LateDataCollectorInterface
|
||||
{
|
||||
private $validator;
|
||||
private $cloner;
|
||||
|
||||
public function __construct(TraceableValidator $validator)
|
||||
{
|
||||
$this->validator = $validator;
|
||||
$this->data = array(
|
||||
'calls' => array(),
|
||||
'violations_count' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function collect(Request $request, Response $response, \Exception $exception = null)
|
||||
{
|
||||
// Everything is collected once, on kernel terminate.
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function lateCollect()
|
||||
{
|
||||
$collected = $this->validator->getCollectedData();
|
||||
$this->data['calls'] = $this->cloneVar($collected);
|
||||
$this->data['violations_count'] += array_reduce($collected, function ($previous, $item) {
|
||||
return $previous += count($item['violations']);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
public function getCalls()
|
||||
{
|
||||
return $this->data['calls'];
|
||||
}
|
||||
|
||||
public function getViolationsCount()
|
||||
{
|
||||
return $this->data['violations_count'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'validator';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function cloneVar($var)
|
||||
{
|
||||
if ($var instanceof Data) {
|
||||
return $var;
|
||||
}
|
||||
|
||||
if (null === $this->cloner) {
|
||||
$this->cloner = new VarCloner();
|
||||
$this->cloner->setMaxItems(-1);
|
||||
$this->cloner->addCasters(array(
|
||||
FormInterface::class => function (FormInterface $f, array $a) {
|
||||
return array(
|
||||
Caster::PREFIX_VIRTUAL.'name' => $f->getName(),
|
||||
Caster::PREFIX_VIRTUAL.'type_class' => new ClassStub(get_class($f->getConfig()->getType()->getInnerType())),
|
||||
Caster::PREFIX_VIRTUAL.'data' => $f->getData(),
|
||||
);
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
return $this->cloner->cloneVar($var, Caster::EXCLUDE_VERBOSE);
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
<?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\Tests\DataCollector;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Validator\ConstraintViolation;
|
||||
use Symfony\Component\Validator\ConstraintViolationList;
|
||||
use Symfony\Component\Validator\DataCollector\ValidatorDataCollector;
|
||||
use Symfony\Component\Validator\Validator\TraceableValidator;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
class ValidatorDataCollectorTest extends TestCase
|
||||
{
|
||||
public function testCollectsValidatorCalls()
|
||||
{
|
||||
$originalValidator = $this->createMock(ValidatorInterface::class);
|
||||
$validator = new TraceableValidator($originalValidator);
|
||||
|
||||
$collector = new ValidatorDataCollector($validator);
|
||||
|
||||
$violations = new ConstraintViolationList(array(
|
||||
$this->createMock(ConstraintViolation::class),
|
||||
$this->createMock(ConstraintViolation::class),
|
||||
));
|
||||
$originalValidator->method('validate')->willReturn($violations);
|
||||
|
||||
$validator->validate(new \stdClass());
|
||||
|
||||
$collector->lateCollect();
|
||||
|
||||
$calls = $collector->getCalls();
|
||||
|
||||
$this->assertCount(1, $calls);
|
||||
$this->assertSame(2, $collector->getViolationsCount());
|
||||
|
||||
$call = $calls[0];
|
||||
|
||||
$this->assertArrayHasKey('caller', $call);
|
||||
$this->assertArrayHasKey('context', $call);
|
||||
$this->assertArrayHasKey('violations', $call);
|
||||
$this->assertCount(2, $call['violations']);
|
||||
}
|
||||
|
||||
protected function createMock($classname)
|
||||
{
|
||||
return $this->getMockBuilder($classname)->disableOriginalConstructor()->getMock();
|
||||
}
|
||||
}
|
@ -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\Tests\Validator;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintViolation;
|
||||
use Symfony\Component\Validator\ConstraintViolationList;
|
||||
use Symfony\Component\Validator\ConstraintViolationListInterface;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Symfony\Component\Validator\Mapping\MetadataInterface;
|
||||
use Symfony\Component\Validator\Validator\ContextualValidatorInterface;
|
||||
use Symfony\Component\Validator\Validator\TraceableValidator;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
class TraceableValidatorTest extends TestCase
|
||||
{
|
||||
public function testValidate()
|
||||
{
|
||||
$originalValidator = $this->createMock(ValidatorInterface::class);
|
||||
$violations = new ConstraintViolationList(array(
|
||||
$this->createMock(ConstraintViolation::class),
|
||||
$this->createMock(ConstraintViolation::class),
|
||||
));
|
||||
$originalValidator->expects($this->exactly(2))->method('validate')->willReturn($violations);
|
||||
|
||||
$validator = new TraceableValidator($originalValidator);
|
||||
|
||||
$object = new \stdClass();
|
||||
$constraints = array($this->createMock(Constraint::class));
|
||||
$groups = array('Default', 'Create');
|
||||
|
||||
$validator->validate($object, $constraints, $groups);
|
||||
$line = __LINE__ - 1;
|
||||
|
||||
$collectedData = $validator->getCollectedData();
|
||||
|
||||
$this->assertCount(1, $collectedData);
|
||||
|
||||
$callData = $collectedData[0];
|
||||
|
||||
$this->assertSame(iterator_to_array($violations), $callData['violations']);
|
||||
|
||||
$this->assertSame(array(
|
||||
'value' => $object,
|
||||
'constraints' => $constraints,
|
||||
'groups' => $groups,
|
||||
), $callData['context']);
|
||||
|
||||
$this->assertEquals(array(
|
||||
'name' => 'TraceableValidatorTest.php',
|
||||
'file' => __FILE__,
|
||||
'line' => $line,
|
||||
), $callData['caller']);
|
||||
|
||||
$validator->validate($object, $constraints, $groups);
|
||||
$collectedData = $validator->getCollectedData();
|
||||
|
||||
$this->assertCount(2, $collectedData);
|
||||
}
|
||||
|
||||
public function testForwardsToOriginalValidator()
|
||||
{
|
||||
$originalValidator = $this->createMock(ValidatorInterface::class);
|
||||
$validator = new TraceableValidator($originalValidator);
|
||||
|
||||
$expects = function ($method) use ($originalValidator) { return $originalValidator->expects($this->once())->method($method); };
|
||||
|
||||
$expects('getMetadataFor')->willReturn($expected = $this->createMock(MetadataInterface::class));
|
||||
$this->assertSame($expected, $validator->getMetadataFor('value'), 'returns original validator getMetadataFor() result');
|
||||
|
||||
$expects('hasMetadataFor')->willReturn($expected = false);
|
||||
$this->assertSame($expected, $validator->hasMetadataFor('value'), 'returns original validator hasMetadataFor() result');
|
||||
|
||||
$expects('inContext')->willReturn($expected = $this->createMock(ContextualValidatorInterface::class));
|
||||
$this->assertSame($expected, $validator->inContext($this->createMock(ExecutionContextInterface::class)), 'returns original validator inContext() result');
|
||||
|
||||
$expects('startContext')->willReturn($expected = $this->createMock(ContextualValidatorInterface::class));
|
||||
$this->assertSame($expected, $validator->startContext(), 'returns original validator startContext() result');
|
||||
|
||||
$expects('validate')->willReturn($expected = $this->createMock(ConstraintViolationListInterface::class));
|
||||
$this->assertSame($expected, $validator->validate('value'), 'returns original validator validate() result');
|
||||
|
||||
$expects('validateProperty')->willReturn($expected = $this->createMock(ConstraintViolationListInterface::class));
|
||||
$this->assertSame($expected, $validator->validateProperty(new \stdClass(), 'property'), 'returns original validator validateProperty() result');
|
||||
|
||||
$expects('validatePropertyValue')->willReturn($expected = $this->createMock(ConstraintViolationListInterface::class));
|
||||
$this->assertSame($expected, $validator->validatePropertyValue(new \stdClass(), 'property', 'value'), 'returns original validator validatePropertyValue() result');
|
||||
}
|
||||
|
||||
protected function createMock($classname)
|
||||
{
|
||||
return $this->getMockBuilder($classname)->disableOriginalConstructor()->getMock();
|
||||
}
|
||||
}
|
131
src/Symfony/Component/Validator/Validator/TraceableValidator.php
Normal file
131
src/Symfony/Component/Validator/Validator/TraceableValidator.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?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\Validator;
|
||||
|
||||
use Symfony\Component\Validator\ConstraintViolationList;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
/**
|
||||
* Collects some data about validator calls.
|
||||
*
|
||||
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
|
||||
*/
|
||||
class TraceableValidator implements ValidatorInterface
|
||||
{
|
||||
private $validator;
|
||||
private $collectedData = array();
|
||||
|
||||
public function __construct(ValidatorInterface $validator)
|
||||
{
|
||||
$this->validator = $validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ConstraintViolationList[]
|
||||
*/
|
||||
public function getCollectedData()
|
||||
{
|
||||
return $this->collectedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMetadataFor($value)
|
||||
{
|
||||
return $this->validator->getMetadataFor($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasMetadataFor($value)
|
||||
{
|
||||
return $this->validator->hasMetadataFor($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validate($value, $constraints = null, $groups = null)
|
||||
{
|
||||
$violations = $this->validator->validate($value, $constraints, $groups);
|
||||
|
||||
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 7);
|
||||
|
||||
$file = $trace[0]['file'];
|
||||
$line = $trace[0]['line'];
|
||||
|
||||
for ($i = 1; $i < 7; ++$i) {
|
||||
if (isset($trace[$i]['class'], $trace[$i]['function'])
|
||||
&& 'validate' === $trace[$i]['function']
|
||||
&& is_a($trace[$i]['class'], ValidatorInterface::class, true)
|
||||
) {
|
||||
$file = $trace[$i]['file'];
|
||||
$line = $trace[$i]['line'];
|
||||
|
||||
while (++$i < 7) {
|
||||
if (isset($trace[$i]['function'], $trace[$i]['file']) && empty($trace[$i]['class']) && 0 !== strpos($trace[$i]['function'], 'call_user_func')) {
|
||||
$file = $trace[$i]['file'];
|
||||
$line = $trace[$i]['line'];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$name = str_replace('\\', '/', $file);
|
||||
$name = substr($name, strrpos($name, '/') + 1);
|
||||
|
||||
$this->collectedData[] = array(
|
||||
'caller' => compact('name', 'file', 'line'),
|
||||
'context' => compact('value', 'constraints', 'groups'),
|
||||
'violations' => iterator_to_array($violations),
|
||||
);
|
||||
|
||||
return $violations;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateProperty($object, $propertyName, $groups = null)
|
||||
{
|
||||
return $this->validator->validateProperty($object, $propertyName, $groups);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validatePropertyValue($objectOrClass, $propertyName, $value, $groups = null)
|
||||
{
|
||||
return $this->validator->validatePropertyValue($objectOrClass, $propertyName, $value, $groups);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function startContext()
|
||||
{
|
||||
return $this->validator->startContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function inContext(ExecutionContextInterface $context)
|
||||
{
|
||||
return $this->validator->inContext($context);
|
||||
}
|
||||
}
|
@ -22,6 +22,8 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/http-foundation": "~2.8|~3.0|~4.0",
|
||||
"symfony/http-kernel": "~2.8|~3.0|~4.0.0",
|
||||
"symfony/var-dumper": "~3.3|~4.0.0",
|
||||
"symfony/intl": "^2.8.18|^3.2.5|~4.0",
|
||||
"symfony/yaml": "~3.3|~4.0",
|
||||
"symfony/config": "~2.8|~3.0|~4.0",
|
||||
|
Reference in New Issue
Block a user