[Validator] Extracted message interpolation logic of ConstraintViolation and used the Translation component for that

This commit is contained in:
Bernhard Schussek 2012-11-27 22:42:05 +01:00
parent 8c320b0dfd
commit 46f751ccf2
20 changed files with 364 additions and 49 deletions

View File

@ -28,6 +28,8 @@ CHANGELOG
As of Symfony 2.3, this method will be typed against `MetadataFactoryInterface` instead.
* [BC BREAK] the switches `traverse` and `deep` in the `Valid` constraint and in `GraphWalker::walkReference`
are ignored for arrays now. Arrays are always traversed recursively.
* added dependency to Translation component
* violation messages are now translated with a TranslatorInterface implementation
2.1.0
-----

View File

@ -18,6 +18,11 @@ namespace Symfony\Component\Validator;
*/
class ConstraintViolation implements ConstraintViolationInterface
{
/**
* @var string
*/
private $message;
/**
* @var string
*/
@ -56,6 +61,7 @@ class ConstraintViolation implements ConstraintViolationInterface
/**
* Creates a new constraint violation.
*
* @param string $message The violation message.
* @param string $messageTemplate The raw violation message.
* @param array $messageParameters The parameters to substitute
* in the raw message.
@ -70,8 +76,9 @@ class ConstraintViolation implements ConstraintViolationInterface
* @param mixed $code The error code of the
* violation, if any.
*/
public function __construct($messageTemplate, array $messageParameters, $root, $propertyPath, $invalidValue, $messagePluralization = null, $code = null)
public function __construct($message, $messageTemplate, array $messageParameters, $root, $propertyPath, $invalidValue, $messagePluralization = null, $code = null)
{
$this->message = $message;
$this->messageTemplate = $messageTemplate;
$this->messageParameters = $messageParameters;
$this->messagePluralization = $messagePluralization;
@ -132,15 +139,7 @@ class ConstraintViolation implements ConstraintViolationInterface
*/
public function getMessage()
{
$parameters = $this->messageParameters;
foreach ($parameters as $i => $parameter) {
if (is_array($parameter)) {
$parameters[$i] = 'Array';
}
}
return strtr($this->messageTemplate, $parameters);
return $this->message;
}
/**

View File

@ -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;
use Symfony\Component\Translation\TranslatorInterface;
/**
* Simple translator implementation that simply replaces the parameters in
* the message IDs.
*
* Does not support translation domains or locales.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class DefaultTranslator implements TranslatorInterface
{
/**
* {@inheritdoc}
*/
public function trans($id, array $parameters = array(), $domain = null, $locale = null)
{
return strtr($id, $parameters);
}
/**
* {@inheritdoc}
*/
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
{
return strtr($id, $parameters);
}
/**
* {@inheritdoc}
*/
public function setLocale($locale)
{
throw new \BadMethodCallException('Unsupported method.');
}
/**
* {@inheritdoc}
*/
public function getLocale()
{
throw new \BadMethodCallException('Unsupported method.');
}
}

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\Validator;
use Symfony\Component\Translation\TranslatorInterface;
/**
* Default implementation of {@link ExecutionContextInterface}.
*
@ -26,6 +28,16 @@ class ExecutionContext implements ExecutionContextInterface
*/
private $globalContext;
/**
* @var TranslatorInterface
*/
private $translator;
/**
* @var null|string
*/
private $translationDomain;
/**
* @var MetadataInterface
*/
@ -49,19 +61,23 @@ class ExecutionContext implements ExecutionContextInterface
/**
* Creates a new execution context.
*
* @param GlobalExecutionContextInterface $globalContext The global context storing node-independent state.
* @param MetadataInterface $metadata The metadata of the validated node.
* @param mixed $value The value of the validated node.
* @param string $group The current validation group.
* @param string $propertyPath The property path to the current node.
* @param GlobalExecutionContextInterface $globalContext The global context storing node-independent state.
* @param TranslatorInterface $translator The translator for translating violation messages.
* @param null|string $translationDomain The domain of the validation messages.
* @param MetadataInterface $metadata The metadata of the validated node.
* @param mixed $value The value of the validated node.
* @param string $group The current validation group.
* @param string $propertyPath The property path to the current node.
*/
public function __construct(GlobalExecutionContextInterface $globalContext, MetadataInterface $metadata = null, $value = null, $group = null, $propertyPath = '')
public function __construct(GlobalExecutionContextInterface $globalContext, TranslatorInterface $translator, $translationDomain = null, MetadataInterface $metadata = null, $value = null, $group = null, $propertyPath = '')
{
if (null === $group) {
$group = Constraint::DEFAULT_GROUP;
}
$this->globalContext = $globalContext;
$this->translator = $translator;
$this->translationDomain = $translationDomain;
$this->metadata = $metadata;
$this->value = $value;
$this->propertyPath = $propertyPath;
@ -74,6 +90,9 @@ class ExecutionContext implements ExecutionContextInterface
public function addViolation($message, array $params = array(), $invalidValue = null, $pluralization = null, $code = null)
{
$this->globalContext->getViolations()->add(new ConstraintViolation(
null === $pluralization
? $this->translator->trans($message, $params, $this->translationDomain)
: $this->translator->transChoice($message, $pluralization, $params, $this->translationDomain),
$message,
$params,
$this->globalContext->getRoot(),
@ -103,6 +122,9 @@ class ExecutionContext implements ExecutionContextInterface
trigger_error('addViolationAtPath() is deprecated since version 2.2 and will be removed in 2.3.', E_USER_DEPRECATED);
$this->globalContext->getViolations()->add(new ConstraintViolation(
null === $pluralization
? $this->translator->trans($message, $params, $this->translationDomain)
: $this->translator->transChoice($message, $pluralization, $params, $this->translationDomain),
$message,
$params,
$this->globalContext->getRoot(),
@ -146,6 +168,9 @@ class ExecutionContext implements ExecutionContextInterface
public function addViolationAt($subPath, $message, array $params = array(), $invalidValue = null, $pluralization = null, $code = null)
{
$this->globalContext->getViolations()->add(new ConstraintViolation(
null === $pluralization
? $this->translator->trans($message, $params, $this->translationDomain)
: $this->translator->transChoice($message, $pluralization, $params, $this->translationDomain),
$message,
$params,
$this->globalContext->getRoot(),

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Validator;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\MemberMetadata;
@ -39,6 +40,16 @@ class GraphWalker
*/
private $metadataFactory;
/**
* @var TranslatorInterface
*/
private $translator;
/**
* @var null|string
*/
private $translationDomain;
/**
* @var array
*/
@ -49,16 +60,20 @@ class GraphWalker
*
* @param ValidationVisitor $visitor
* @param MetadataFactoryInterface $metadataFactory
* @param TranslatorInterface $translator
* @param null|string $translationDomain
* @param array $validatedObjects
*
* @deprecated Deprecated since version 2.2, to be removed in 2.3.
*/
public function __construct(ValidationVisitor $visitor, MetadataFactoryInterface $metadataFactory, array &$validatedObjects = array())
public function __construct(ValidationVisitor $visitor, MetadataFactoryInterface $metadataFactory, TranslatorInterface $translator, $translationDomain = null, array &$validatedObjects = array())
{
trigger_error('GraphWalker is deprecated since version 2.2 and will be removed in 2.3. This class has been replaced by ValidationVisitorInterface and MetadataInterface.', E_USER_DEPRECATED);
$this->visitor = $visitor;
$this->metadataFactory = $metadataFactory;
$this->translator = $translator;
$this->translationDomain = $translationDomain;
$this->validatedObjects = &$validatedObjects;
}
@ -208,6 +223,8 @@ class GraphWalker
$context = new ExecutionContext(
$this->visitor,
$this->translator,
$this->translationDomain,
$metadata,
$value,
$group,

View File

@ -129,6 +129,6 @@ EOF;
protected function getViolation($message, $root = null, $propertyPath = null)
{
return new ConstraintViolation($message, array(), $root, $propertyPath, null);
return new ConstraintViolation($message, $message, array(), $root, $propertyPath, null);
}
}

View File

@ -18,6 +18,7 @@ class ConstraintViolationTest extends \PHPUnit_Framework_TestCase
public function testToStringHandlesArrays()
{
$violation = new ConstraintViolation(
'Array',
'{{ value }}',
array('{{ value }}' => array(1, 2, 3)),
'Root',

View File

@ -19,11 +19,14 @@ use Symfony\Component\Validator\ExecutionContext;
class ExecutionContextTest extends \PHPUnit_Framework_TestCase
{
const TRANS_DOMAIN = 'trans_domain';
private $visitor;
private $violations;
private $metadata;
private $metadataFactory;
private $globalContext;
private $translator;
/**
* @var ExecutionContext
@ -51,7 +54,8 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
$this->globalContext->expects($this->any())
->method('getMetadataFactory')
->will($this->returnValue($this->metadataFactory));
$this->context = new ExecutionContext($this->globalContext, $this->metadata, 'currentValue', 'Group', 'foo.bar');
$this->translator = $this->getMock('Symfony\Component\Translation\TranslatorInterface');
$this->context = new ExecutionContext($this->globalContext, $this->translator, self::TRANS_DOMAIN, $this->metadata, 'currentValue', 'Group', 'foo.bar');
}
protected function tearDown()
@ -82,7 +86,7 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
{
// BC
$this->metadata = new ClassMetadata(__NAMESPACE__ . '\ExecutionContextTest_TestClass');
$this->context = new ExecutionContext($this->globalContext, $this->metadata, 'currentValue', 'Group', 'foo.bar');
$this->context = new ExecutionContext($this->globalContext, $this->translator, self::TRANS_DOMAIN, $this->metadata, 'currentValue', 'Group', 'foo.bar');
$this->assertSame(__NAMESPACE__ . '\ExecutionContextTest_TestClass', $this->context->getCurrentClass());
$this->assertNull($this->context->getCurrentProperty());
@ -92,7 +96,7 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
{
// BC
$this->metadata = new PropertyMetadata(__NAMESPACE__ . '\ExecutionContextTest_TestClass', 'myProperty');
$this->context = new ExecutionContext($this->globalContext, $this->metadata, 'currentValue', 'Group', 'foo.bar');
$this->context = new ExecutionContext($this->globalContext, $this->translator, self::TRANS_DOMAIN, $this->metadata, 'currentValue', 'Group', 'foo.bar');
$this->assertSame(__NAMESPACE__ . '\ExecutionContextTest_TestClass', $this->context->getCurrentClass());
$this->assertSame('myProperty', $this->context->getCurrentProperty());
@ -111,10 +115,16 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
public function testAddViolation()
{
$this->translator->expects($this->once())
->method('trans')
->with('Error', array('foo' => 'bar'))
->will($this->returnValue('Translated error'));
$this->context->addViolation('Error', array('foo' => 'bar'), 'invalid');
$this->assertEquals(new ConstraintViolationList(array(
new ConstraintViolation(
'Translated error',
'Error',
array('foo' => 'bar'),
'Root',
@ -126,10 +136,16 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
public function testAddViolationUsesPreconfiguredValueIfNotPassed()
{
$this->translator->expects($this->once())
->method('trans')
->with('Error', array())
->will($this->returnValue('Translated error'));
$this->context->addViolation('Error');
$this->assertEquals(new ConstraintViolationList(array(
new ConstraintViolation(
'Translated error',
'Error',
array(),
'Root',
@ -141,21 +157,32 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
public function testAddViolationUsesPassedNullValue()
{
$this->translator->expects($this->once())
->method('trans')
->with('Error', array('foo1' => 'bar1'))
->will($this->returnValue('Translated error'));
$this->translator->expects($this->once())
->method('transChoice')
->with('Choice error', 1, array('foo2' => 'bar2'))
->will($this->returnValue('Translated choice error'));
// passed null value should override preconfigured value "invalid"
$this->context->addViolation('Error', array('foo' => 'bar'), null);
$this->context->addViolation('Error', array('foo' => 'bar'), null, 1);
$this->context->addViolation('Error', array('foo1' => 'bar1'), null);
$this->context->addViolation('Choice error', array('foo2' => 'bar2'), null, 1);
$this->assertEquals(new ConstraintViolationList(array(
new ConstraintViolation(
'Translated error',
'Error',
array('foo' => 'bar'),
array('foo1' => 'bar1'),
'Root',
'foo.bar',
null
),
new ConstraintViolation(
'Error',
array('foo' => 'bar'),
'Translated choice error',
'Choice error',
array('foo2' => 'bar2'),
'Root',
'foo.bar',
null,
@ -166,11 +193,17 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
public function testAddViolationAtPath()
{
$this->translator->expects($this->once())
->method('trans')
->with('Error', array('foo' => 'bar'))
->will($this->returnValue('Translated error'));
// override preconfigured property path
$this->context->addViolationAtPath('bar.baz', 'Error', array('foo' => 'bar'), 'invalid');
$this->assertEquals(new ConstraintViolationList(array(
new ConstraintViolation(
'Translated error',
'Error',
array('foo' => 'bar'),
'Root',
@ -182,10 +215,16 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
public function testAddViolationAtPathUsesPreconfiguredValueIfNotPassed()
{
$this->translator->expects($this->once())
->method('trans')
->with('Error', array())
->will($this->returnValue('Translated error'));
$this->context->addViolationAtPath('bar.baz', 'Error');
$this->assertEquals(new ConstraintViolationList(array(
new ConstraintViolation(
'Translated error',
'Error',
array(),
'Root',
@ -197,12 +236,22 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
public function testAddViolationAtPathUsesPassedNullValue()
{
$this->translator->expects($this->once())
->method('trans')
->with('Error', array('foo' => 'bar'))
->will($this->returnValue('Translated error'));
$this->translator->expects($this->once())
->method('transChoice')
->with('Choice error', 3, array('foo' => 'bar'))
->will($this->returnValue('Translated choice error'));
// passed null value should override preconfigured value "invalid"
$this->context->addViolationAtPath('bar.baz', 'Error', array('foo' => 'bar'), null);
$this->context->addViolationAtPath('bar.baz', 'Error', array('foo' => 'bar'), null, 1);
$this->context->addViolationAtPath('bar.baz', 'Choice error', array('foo' => 'bar'), null, 3);
$this->assertEquals(new ConstraintViolationList(array(
new ConstraintViolation(
'Translated error',
'Error',
array('foo' => 'bar'),
'Root',
@ -210,23 +259,30 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
null
),
new ConstraintViolation(
'Error',
'Translated choice error',
'Choice error',
array('foo' => 'bar'),
'Root',
'bar.baz',
null,
1
3
),
)), $this->context->getViolations());
}
public function testAddViolationAt()
{
$this->translator->expects($this->once())
->method('trans')
->with('Error', array('foo' => 'bar'))
->will($this->returnValue('Translated error'));
// override preconfigured property path
$this->context->addViolationAt('bam.baz', 'Error', array('foo' => 'bar'), 'invalid');
$this->assertEquals(new ConstraintViolationList(array(
new ConstraintViolation(
'Translated error',
'Error',
array('foo' => 'bar'),
'Root',
@ -238,10 +294,16 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
public function testAddViolationAtUsesPreconfiguredValueIfNotPassed()
{
$this->translator->expects($this->once())
->method('trans')
->with('Error', array())
->will($this->returnValue('Translated error'));
$this->context->addViolationAt('bam.baz', 'Error');
$this->assertEquals(new ConstraintViolationList(array(
new ConstraintViolation(
'Translated error',
'Error',
array(),
'Root',
@ -253,12 +315,22 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
public function testAddViolationAtUsesPassedNullValue()
{
$this->translator->expects($this->once())
->method('trans')
->with('Error', array('foo' => 'bar'))
->will($this->returnValue('Translated error'));
$this->translator->expects($this->once())
->method('transChoice')
->with('Choice error', 2, array('foo' => 'bar'))
->will($this->returnValue('Translated choice error'));
// passed null value should override preconfigured value "invalid"
$this->context->addViolationAt('bam.baz', 'Error', array('foo' => 'bar'), null);
$this->context->addViolationAt('bam.baz', 'Error', array('foo' => 'bar'), null, 1);
$this->context->addViolationAt('bam.baz', 'Choice error', array('foo' => 'bar'), null, 2);
$this->assertEquals(new ConstraintViolationList(array(
new ConstraintViolation(
'Translated error',
'Error',
array('foo' => 'bar'),
'Root',
@ -266,12 +338,13 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
null
),
new ConstraintViolation(
'Error',
'Translated choice error',
'Choice error',
array('foo' => 'bar'),
'Root',
'foo.bar.bam.baz',
null,
1
2
),
)), $this->context->getViolations());
}
@ -293,7 +366,7 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
public function testGetPropertyPathWithEmptyCurrentPropertyPath()
{
$this->context = new ExecutionContext($this->globalContext, $this->metadata, 'currentValue', 'Group', '');
$this->context = new ExecutionContext($this->globalContext, $this->translator, self::TRANS_DOMAIN, $this->metadata, 'currentValue', 'Group', '');
$this->assertEquals('bam.baz', $this->context->getPropertyPath('bam.baz'));
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Validator\Tests;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintAValidator;
use Symfony\Component\Validator\DefaultTranslator;
use Symfony\Component\Validator\ValidationVisitor;
use Symfony\Component\Validator\Tests\Fixtures\Entity;
use Symfony\Component\Validator\Tests\Fixtures\Reference;
@ -53,7 +54,7 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->metadataFactory = new FakeMetadataFactory();
$this->visitor = new ValidationVisitor('Root', $this->metadataFactory, new ConstraintValidatorFactory());
$this->visitor = new ValidationVisitor('Root', $this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator());
$this->walker = $this->visitor->getGraphWalker();
$this->metadata = new ClassMetadata(self::CLASSNAME);
$this->metadataFactory->addMetadata($this->metadata);
@ -172,6 +173,7 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
// validated
$violations = new ConstraintViolationList();
$violations->add(new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -204,6 +206,7 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
// "Default" was launched
$violations = new ConstraintViolationList();
$violations->add(new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -231,6 +234,7 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
// Only group "Second" was validated
$violations = new ConstraintViolationList();
$violations->add(new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -285,6 +289,7 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
$violations = new ConstraintViolationList();
$violations->add(new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -317,6 +322,7 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
$violations = new ConstraintViolationList();
$violations->add(new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -350,6 +356,7 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
$violations = new ConstraintViolationList();
$violations->add(new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -449,6 +456,7 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
$violations = new ConstraintViolationList();
$violations->add(new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -515,6 +523,7 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
$violations = new ConstraintViolationList();
$violations->add(new ConstraintViolation(
'message',
'message',
array('param' => 'value'),
'Root',

View File

@ -14,6 +14,7 @@ namespace Symfony\Component\Validator\Tests;
use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory;
use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\Tests\Fixtures\Reference;
use Symfony\Component\Validator\DefaultTranslator;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\Tests\Fixtures\FailingConstraint;
@ -49,7 +50,7 @@ class ValidationVisitorTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->metadataFactory = new FakeMetadataFactory();
$this->visitor = new ValidationVisitor('Root', $this->metadataFactory, new ConstraintValidatorFactory());
$this->visitor = new ValidationVisitor('Root', $this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator());
$this->metadata = new ClassMetadata(self::CLASS_NAME);
$this->metadataFactory->addMetadata($this->metadata);
}
@ -154,6 +155,7 @@ class ValidationVisitorTest extends \PHPUnit_Framework_TestCase
// validated
$violations = new ConstraintViolationList(array(
new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -187,6 +189,7 @@ class ValidationVisitorTest extends \PHPUnit_Framework_TestCase
// "Default" was launched
$violations = new ConstraintViolationList(array(
new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -215,6 +218,7 @@ class ValidationVisitorTest extends \PHPUnit_Framework_TestCase
// Only group "Second" was validated
$violations = new ConstraintViolationList(array(
new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -243,6 +247,7 @@ class ValidationVisitorTest extends \PHPUnit_Framework_TestCase
$violations = new ConstraintViolationList(array(
// generated by the root object
new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -251,6 +256,7 @@ class ValidationVisitorTest extends \PHPUnit_Framework_TestCase
),
// generated by the reference
new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -278,6 +284,7 @@ class ValidationVisitorTest extends \PHPUnit_Framework_TestCase
$violations = new ConstraintViolationList(array(
// generated by the root object
new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -286,6 +293,7 @@ class ValidationVisitorTest extends \PHPUnit_Framework_TestCase
),
// generated by the reference
new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -313,6 +321,7 @@ class ValidationVisitorTest extends \PHPUnit_Framework_TestCase
$violations = new ConstraintViolationList(array(
// generated by the root object
new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -321,6 +330,7 @@ class ValidationVisitorTest extends \PHPUnit_Framework_TestCase
),
// generated by the reference
new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -352,6 +362,7 @@ class ValidationVisitorTest extends \PHPUnit_Framework_TestCase
$violations = new ConstraintViolationList(array(
// generated by the root object
new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -414,6 +425,7 @@ class ValidationVisitorTest extends \PHPUnit_Framework_TestCase
$violations = new ConstraintViolationList(array(
// generated by the root object
new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -489,6 +501,7 @@ class ValidationVisitorTest extends \PHPUnit_Framework_TestCase
$violations = new ConstraintViolationList(array(
// generated by the root object
new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',
@ -497,6 +510,7 @@ class ValidationVisitorTest extends \PHPUnit_Framework_TestCase
),
// nothing generated by the reference!
new ConstraintViolation(
'Failed',
'Failed',
array(),
'Root',

View File

@ -96,8 +96,8 @@ class ValidatorBuilderTest extends \PHPUnit_Framework_TestCase
public function testSetMetadataCache()
{
$this->assertSame($this->builder, $this->builder->setMetadataCache($this->getMock(
'Symfony\Component\Validator\Mapping\Cache\CacheInterface'))
$this->assertSame($this->builder, $this->builder->setMetadataCache(
$this->getMock('Symfony\Component\Validator\Mapping\Cache\CacheInterface'))
);
}
@ -107,4 +107,16 @@ class ValidatorBuilderTest extends \PHPUnit_Framework_TestCase
$this->getMock('Symfony\Component\Validator\ConstraintValidatorFactoryInterface'))
);
}
public function testSetTranslator()
{
$this->assertSame($this->builder, $this->builder->setTranslator(
$this->getMock('Symfony\Component\Translation\TranslatorInterface'))
);
}
public function testSetTranslationDomain()
{
$this->assertSame($this->builder, $this->builder->setTranslationDomain('TRANS_DOMAIN'));
}
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Validator\Tests;
use Symfony\Component\Validator\Validator;
use Symfony\Component\Validator\DefaultTranslator;
use Symfony\Component\Validator\Mapping\ClassMetadataFactoryAdapter;
use Symfony\Component\Validator\ValidatorContext;
@ -57,6 +58,6 @@ class ValidatorContextTest extends \PHPUnit_Framework_TestCase
->setConstraintValidatorFactory($validatorFactory)
->getValidator();
$this->assertEquals(new Validator(new ClassMetadataFactoryAdapter($metadataFactory), $validatorFactory), $validator);
$this->assertEquals(new Validator(new ClassMetadataFactoryAdapter($metadataFactory), $validatorFactory, new DefaultTranslator()), $validator);
}
}

View File

@ -14,6 +14,7 @@ namespace Symfony\Component\Validator\Tests;
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\Validator\Mapping\ClassMetadataFactoryAdapter;
use Symfony\Component\Validator\Validator;
use Symfony\Component\Validator\DefaultTranslator;
use Symfony\Component\Validator\ValidatorContext;
use Symfony\Component\Validator\ValidatorFactory;
use Symfony\Component\Validator\ConstraintValidatorFactory;
@ -78,7 +79,7 @@ class ValidatorFactoryTest extends \PHPUnit_Framework_TestCase
$validator = $this->factory->getValidator();
$this->assertEquals(new Validator(new ClassMetadataFactoryAdapter($metadataFactory), $validatorFactory), $validator);
$this->assertEquals(new Validator(new ClassMetadataFactoryAdapter($metadataFactory), $validatorFactory, new DefaultTranslator()), $validator);
}
public function testBuildDefaultFromAnnotationsWithCustomNamespaces()

View File

@ -16,6 +16,7 @@ use Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity;
use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory;
use Symfony\Component\Validator\Tests\Fixtures\FailingConstraint;
use Symfony\Component\Validator\Validator;
use Symfony\Component\Validator\DefaultTranslator;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\ConstraintValidatorFactory;
@ -37,7 +38,7 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->metadataFactory = new FakeMetadataFactory();
$this->validator = new Validator($this->metadataFactory, new ConstraintValidatorFactory());
$this->validator = new Validator($this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator());
}
protected function tearDown()
@ -59,6 +60,7 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
// Only the constraint of group "Default" failed
$violations = new ConstraintViolationList();
$violations->add(new ConstraintViolation(
'Failed',
'Failed',
array(),
$entity,
@ -82,6 +84,7 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
// Only the constraint of group "Custom" failed
$violations = new ConstraintViolationList();
$violations->add(new ConstraintViolation(
'Failed',
'Failed',
array(),
$entity,
@ -107,6 +110,7 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
// The constraints of both groups failed
$violations = new ConstraintViolationList();
$violations->add(new ConstraintViolation(
'Failed',
'Failed',
array(),
$entity,
@ -114,6 +118,7 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
''
));
$violations->add(new ConstraintViolation(
'Failed',
'Failed',
array(),
$entity,
@ -141,6 +146,7 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
$violations = new ConstraintViolationList();
$violations->add(new ConstraintViolation(
'Failed',
'Failed',
array(),
$entity,
@ -154,6 +160,7 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
$violations = new ConstraintViolationList();
$violations->add(new ConstraintViolation(
'Failed',
'Failed',
array(),
$entity,
@ -198,6 +205,7 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
{
$violations = new ConstraintViolationList();
$violations->add(new ConstraintViolation(
'Failed',
'Failed',
array(),
'',
@ -232,7 +240,7 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
->method('getMetadataFor')
->with('VALUE')
->will($this->returnValue($metadata));
$this->validator = new Validator($this->metadataFactory, new ConstraintValidatorFactory());
$this->validator = new Validator($this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator());
$this->validator->validateProperty('VALUE', 'someProperty');
}
@ -249,7 +257,7 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
->method('getMetadataFor')
->with('VALUE')
->will($this->returnValue($metadata));
$this->validator = new Validator($this->metadataFactory, new ConstraintValidatorFactory());
$this->validator = new Validator($this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator());
$this->validator->validatePropertyValue('VALUE', 'someProperty', 'propertyValue');
}

View File

@ -13,6 +13,7 @@ namespace Symfony\Component\Validator;
use Symfony\Component\Validator\Exception\NoSuchMetadataException;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Translation\TranslatorInterface;
/**
* Default implementation of {@link ValidationVisitorInterface} and
@ -37,6 +38,16 @@ class ValidationVisitor implements ValidationVisitorInterface, GlobalExecutionCo
*/
private $validatorFactory;
/**
* @var TranslatorInterface
*/
private $translator;
/**
* @var null|string
*/
private $translationDomain;
/**
* @var array
*/
@ -65,11 +76,13 @@ class ValidationVisitor implements ValidationVisitorInterface, GlobalExecutionCo
* @param mixed $root The value passed to the validator.
* @param MetadataFactoryInterface $metadataFactory The factory for obtaining metadata instances.
* @param ConstraintValidatorFactoryInterface $validatorFactory The factory for creating constraint validators.
* @param TranslatorInterface $translator The translator for translating violation messages.
* @param string|null $translationDomain The domain of the translation messages.
* @param ObjectInitializerInterface[] $objectInitializers The initializers for preparing objects before validation.
*
* @throws UnexpectedTypeException If any of the object initializers is not an instance of ObjectInitializerInterface
*/
public function __construct($root, MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, array $objectInitializers = array())
public function __construct($root, MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, TranslatorInterface $translator, $translationDomain = null, array $objectInitializers = array())
{
foreach ($objectInitializers as $initializer) {
if (!$initializer instanceof ObjectInitializerInterface) {
@ -80,6 +93,8 @@ class ValidationVisitor implements ValidationVisitorInterface, GlobalExecutionCo
$this->root = $root;
$this->metadataFactory = $metadataFactory;
$this->validatorFactory = $validatorFactory;
$this->translator = $translator;
$this->translationDomain = $translationDomain;
$this->objectInitializers = $objectInitializers;
$this->violations = new ConstraintViolationList();
}
@ -91,6 +106,8 @@ class ValidationVisitor implements ValidationVisitorInterface, GlobalExecutionCo
{
$context = new ExecutionContext(
$this,
$this->translator,
$this->translationDomain,
$metadata,
$value,
$group,
@ -161,7 +178,7 @@ class ValidationVisitor implements ValidationVisitorInterface, GlobalExecutionCo
trigger_error('getGraphWalker() is deprecated since version 2.2 and will be removed in 2.3.', E_USER_DEPRECATED);
if (null === $this->graphWalker) {
$this->graphWalker = new GraphWalker($this, $this->metadataFactory, $this->validatedObjects);
$this->graphWalker = new GraphWalker($this, $this->metadataFactory, $this->translator, $this->translationDomain, $this->validatedObjects);
}
return $this->graphWalker;

View File

@ -13,6 +13,7 @@ namespace Symfony\Component\Validator;
use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\Exception\ValidatorException;
use Symfony\Component\Translation\TranslatorInterface;
/**
* Default implementation of {@link ValidatorInterface}.
@ -32,6 +33,16 @@ class Validator implements ValidatorInterface
*/
private $validatorFactory;
/**
* @var TranslatorInterface
*/
private $translator;
/**
* @var null|string
*/
private $translationDomain;
/**
* @var array
*/
@ -40,11 +51,15 @@ class Validator implements ValidatorInterface
public function __construct(
MetadataFactoryInterface $metadataFactory,
ConstraintValidatorFactoryInterface $validatorFactory,
TranslatorInterface $translator,
$translationDomain = null,
array $objectInitializers = array()
)
{
$this->metadataFactory = $metadataFactory;
$this->validatorFactory = $validatorFactory;
$this->translator = $translator;
$this->translationDomain = $translationDomain;
$this->objectInitializers = $objectInitializers;
}
@ -137,7 +152,7 @@ class Validator implements ValidatorInterface
*/
public function validateValue($value, $constraints, $groups = null)
{
$context = new ExecutionContext($this->createVisitor(null));
$context = new ExecutionContext($this->createVisitor(null), $this->translator, $this->translationDomain);
$constraints = is_array($constraints) ? $constraints : array($constraints);
@ -176,7 +191,14 @@ class Validator implements ValidatorInterface
*/
private function createVisitor($root)
{
return new ValidationVisitor($root, $this->metadataFactory, $this->validatorFactory, $this->objectInitializers);
return new ValidationVisitor(
$root,
$this->metadataFactory,
$this->validatorFactory,
$this->translator,
$this->translationDomain,
$this->objectInitializers
);
}
/**

View File

@ -23,6 +23,7 @@ use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Validator\Mapping\Loader\YamlFilesLoader;
use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader;
use Symfony\Component\Validator\Mapping\Loader\XmlFilesLoader;
use Symfony\Component\Translation\TranslatorInterface;
use Doctrine\Common\Annotations\Reader;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\CachedReader;
@ -75,6 +76,16 @@ class ValidatorBuilder implements ValidatorBuilderInterface
*/
private $metadataCache;
/**
* @var TranslatorInterface
*/
private $translator;
/**
* @var null|string
*/
private $translationDomain;
/**
* {@inheritdoc}
*/
@ -254,6 +265,26 @@ class ValidatorBuilder implements ValidatorBuilderInterface
return $this;
}
/**
* {@inheritdoc}
*/
public function setTranslator(TranslatorInterface $translator)
{
$this->translator = $translator;
return $this;
}
/**
* {@inheritdoc}
*/
public function setTranslationDomain($translationDomain)
{
$this->translationDomain = $translationDomain;
return $this;
}
/**
* {@inheritdoc}
*/
@ -296,7 +327,8 @@ class ValidatorBuilder implements ValidatorBuilderInterface
}
$validatorFactory = $this->validatorFactory ?: new ConstraintValidatorFactory();
$translator = $this->translator ?: new DefaultTranslator();
return new Validator($metadataFactory, $validatorFactory, $this->initializers);
return new Validator($metadataFactory, $validatorFactory, $translator, $this->translationDomain, $this->initializers);
}
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Validator;
use Symfony\Component\Validator\Mapping\Cache\CacheInterface;
use Symfony\Component\Translation\TranslatorInterface;
use Doctrine\Common\Annotations\Reader;
/**
@ -139,6 +140,28 @@ interface ValidatorBuilderInterface
*/
public function setConstraintValidatorFactory(ConstraintValidatorFactoryInterface $validatorFactory);
/**
* Sets the translator used for translating violation messages.
*
* @param TranslatorInterface $translator The translator instance.
*
* @return ValidatorBuilderInterface The builder object.
*/
public function setTranslator(TranslatorInterface $translator);
/**
* Sets the default translation domain of violation messages.
*
* The same message can have different translations in different domains.
* Pass the domain that is used for violation messages by default to this
* method.
*
* @param string $translationDomain The translation domain of the violation messages.
*
* @return ValidatorBuilderInterface The builder object.
*/
public function setTranslationDomain($translationDomain);
/**
* Builds and returns a new validator object.
*

View File

@ -89,7 +89,8 @@ class ValidatorContext implements ValidatorContextInterface
return new Validator(
$this->metadataFactory,
$this->constraintValidatorFactory
$this->constraintValidatorFactory,
new DefaultTranslator()
);
}

View File

@ -16,7 +16,8 @@
}
],
"require": {
"php": ">=5.3.3"
"php": ">=5.3.3",
"symfony/translation": "2.2.*"
},
"require-dev": {
"symfony/http-foundation": "2.2.*",