[Validator] Allow objects implementing __toString() to be used as violation messages

[Validator] updated changelog

[Validator] updated typehint for ConstraintViolationInterface::getMessage()

[Validator] fixed spacing issue inadvertantly added in previous commit

[Validator] fixed coding standard issues

[Validator] Address feedback

[Validator] Fix coding standard violation

[Validator] update tests

[Validator] Address feedback, Round 2

[Validator] Document ConstraintViolationBuilder::__construct()  parameter

[Validator] Update changelog

[Validator] Adjust parameter documentation order
This commit is contained in:
Michael Lutz 2019-08-08 12:57:01 -04:00
parent e0ccbf667a
commit 79f4dcd2dc
6 changed files with 60 additions and 6 deletions

View File

@ -20,6 +20,7 @@ CHANGELOG
`maxPropertyPath` options
* added a new `notInRangeMessage` option to the `Range` constraint that will
be used in the violation builder when both `min` and `max` are not null
* added ability to use stringable objects as violation messages
4.3.0
-----

View File

@ -32,7 +32,7 @@ class ConstraintViolation implements ConstraintViolationInterface
/**
* Creates a new constraint violation.
*
* @param string $message The violation message
* @param string $message The violation message as a string or a stringable object
* @param string $messageTemplate The raw violation message
* @param array $parameters The parameters to substitute in the
* raw violation message
@ -47,7 +47,7 @@ class ConstraintViolation implements ConstraintViolationInterface
* @param string|null $code The error code of the violation
* @param mixed $cause The cause of the violation
*/
public function __construct(?string $message, ?string $messageTemplate, array $parameters, $root, ?string $propertyPath, $invalidValue, int $plural = null, $code = null, Constraint $constraint = null, $cause = null)
public function __construct($message, ?string $messageTemplate, array $parameters, $root, ?string $propertyPath, $invalidValue, int $plural = null, $code = null, Constraint $constraint = null, $cause = null)
{
if (null === $message) {
@trigger_error(sprintf('Passing a null message when instantiating a "%s" is deprecated since Symfony 4.4.', __CLASS__), E_USER_DEPRECATED);
@ -58,6 +58,10 @@ class ConstraintViolation implements ConstraintViolationInterface
@trigger_error(sprintf('Not using a string as the error code in %s() is deprecated since Symfony 4.4. A type-hint will be added in 5.0.', __METHOD__), E_USER_DEPRECATED);
}
if (!\is_string($message) && !(\is_object($message) && method_exists($message, '__toString'))) {
throw new \TypeError('Constraint violation message should be a string or an object which implements the __toString() method.');
}
$this->message = $message;
$this->messageTemplate = $messageTemplate;
$this->parameters = $parameters;

View File

@ -36,7 +36,7 @@ interface ConstraintViolationInterface
/**
* Returns the violation message.
*
* @return string The violation message
* @return string The violation message as a string or a stringable object
*/
public function getMessage();

View File

@ -64,7 +64,7 @@ interface ExecutionContextInterface
/**
* Adds a violation at the current node of the validation graph.
*
* @param string $message The error message
* @param string $message The error message as a string or a stringable object
* @param array $params The parameters substituted in the error message
*/
public function addViolation($message, array $params = []);
@ -81,7 +81,7 @@ interface ExecutionContextInterface
* ->setTranslationDomain('number_validation')
* ->addViolation();
*
* @param string $message The error message
* @param string $message The error message as a string or a stringable object
* @param array $parameters The parameters substituted in the error message
*
* @return ConstraintViolationBuilderInterface The violation builder

View File

@ -13,6 +13,8 @@ namespace Symfony\Component\Validator\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\Tests\Fixtures\CustomArrayObject;
use Symfony\Component\Validator\Tests\Fixtures\ToString;
class ConstraintViolationTest extends TestCase
{
@ -109,6 +111,52 @@ EOF;
$this->assertSame($expected, (string) $violation);
}
public function testMessageCanBeStringableObject()
{
$message = new ToString();
$violation = new ConstraintViolation(
$message,
(string) $message,
[],
'Root',
'property.path',
null
);
$expected = <<<'EOF'
Root.property.path:
toString
EOF;
$this->assertSame($expected, (string) $violation);
$this->assertSame($message, $violation->getMessage());
}
public function testMessageCannotBeArray()
{
$this->expectException(\TypeError::class);
$violation = new ConstraintViolation(
['cannot be an array'],
'',
[],
'Root',
'property.path',
null
);
}
public function testMessageObjectMustBeStringable()
{
$this->expectException(\TypeError::class);
$violation = new ConstraintViolation(
new CustomArrayObject(),
'',
[],
'Root',
'property.path',
null
);
}
/**
* @group legacy
* @expectedDeprecation Not using a string as the error code in Symfony\Component\Validator\ConstraintViolation::__construct() is deprecated since Symfony 4.4. A type-hint will be added in 5.0.

View File

@ -45,9 +45,10 @@ class ConstraintViolationBuilder implements ConstraintViolationBuilderInterface
private $cause;
/**
* @param string $message The error message as a string or a stringable object
* @param TranslatorInterface $translator
*/
public function __construct(ConstraintViolationList $violations, Constraint $constraint, ?string $message, array $parameters, $root, string $propertyPath, $invalidValue, $translator, string $translationDomain = null)
public function __construct(ConstraintViolationList $violations, Constraint $constraint, $message, array $parameters, $root, string $propertyPath, $invalidValue, $translator, string $translationDomain = null)
{
if (null === $message) {
@trigger_error(sprintf('Passing a null message when instantiating a "%s" is deprecated since Symfony 4.4.', __CLASS__), E_USER_DEPRECATED);