[PropertyAccess] Show property path in all exception messages

This commit is contained in:
Mikael Pajunen 2015-01-08 19:24:48 +02:00 committed by Fabien Potencier
parent 54e07c95dc
commit b286863bec
7 changed files with 93 additions and 9 deletions

View File

@ -83,3 +83,25 @@ Serializer
$nameConverter = new CamelCaseToSnakeCaseNameConverter(array('fooBar', 'barFoo'));
$normalizer = new GetSetMethodNormalizer(null, $nameConverter);
```
PropertyAccess
--------------
* `UnexpectedTypeException` now expects three constructor arguments: The invalid property value,
the `PropertyPathInterface` object and the current index of the property path.
Before:
```php
use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException;
new UnexpectedTypeException($value, $expectedType);
```
After:
```php
use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException;
new UnexpectedTypeException($value, $path, $pathIndex);
```

View File

@ -1,6 +1,12 @@
CHANGELOG
=========
2.7.0
------
* `UnexpectedTypeException` now expects three constructor arguments: The invalid property value,
the `PropertyPathInterface` object and the current index of the property path.
2.5.0
------

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\PropertyAccess\Exception;
use Symfony\Component\PropertyAccess\PropertyPathInterface;
/**
* Thrown when a value does not match an expected type.
*
@ -18,8 +20,31 @@ namespace Symfony\Component\PropertyAccess\Exception;
*/
class UnexpectedTypeException extends RuntimeException
{
public function __construct($value, $expectedType)
/**
* @param mixed $value The unexpected value found while traversing property path
* @param PropertyPathInterface $path The property path
* @param int $pathIndex The property path index when the unexpected value was found
*/
public function __construct($value, $path, $pathIndex = null)
{
parent::__construct(sprintf('Expected argument of type "%s", "%s" given', $expectedType, is_object($value) ? get_class($value) : gettype($value)));
if (func_num_args() === 3 && $path instanceof PropertyPathInterface) {
$message = sprintf(
'PropertyAccessor requires a graph of objects or arrays to operate on, '.
'but it found type "%s" while trying to traverse path "%s" at property "%s".',
gettype($value),
(string) $path,
$path->getElement($pathIndex)
);
} else {
trigger_error('The '.__CLASS__.' constructor now expects 3 arguments: the invalid property value, the '.__NAMESPACE__.'\PropertyPathInterface object and the current index of the property path.', E_USER_DEPRECATED);
$message = sprintf(
'Expected argument of type "%s", "%s" given',
$path,
is_object($value) ? get_class($value) : gettype($value)
);
}
parent::__construct($message);
}
}

View File

@ -97,7 +97,7 @@ class PropertyAccessor implements PropertyAccessorInterface
if ($overwrite) {
if (!is_object($objectOrArray) && !is_array($objectOrArray)) {
throw new UnexpectedTypeException($objectOrArray, 'object or array');
throw new UnexpectedTypeException($objectOrArray, $propertyPath, $i);
}
$property = $propertyPath->getElement($i);
@ -221,7 +221,7 @@ class PropertyAccessor implements PropertyAccessorInterface
for ($i = 0; $i < $lastIndex; ++$i) {
if (!is_object($objectOrArray) && !is_array($objectOrArray)) {
throw new UnexpectedTypeException($objectOrArray, 'object or array');
throw new UnexpectedTypeException($objectOrArray, $propertyPath, $i);
}
$property = $propertyPath->getElement($i);

View File

@ -11,9 +11,9 @@
namespace Symfony\Component\PropertyAccess;
use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException;
use Symfony\Component\PropertyAccess\Exception\InvalidPropertyPathException;
use Symfony\Component\PropertyAccess\Exception\OutOfBoundsException;
use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException;
/**
* Default implementation of {@link PropertyPathInterface}.
@ -70,7 +70,7 @@ class PropertyPath implements \IteratorAggregate, PropertyPathInterface
*
* @param PropertyPath|string $propertyPath The property path as string or instance
*
* @throws UnexpectedTypeException If the given path is not a string
* @throws InvalidArgumentException If the given path is not a string
* @throws InvalidPropertyPathException If the syntax of the property path is not valid
*/
public function __construct($propertyPath)
@ -87,7 +87,12 @@ class PropertyPath implements \IteratorAggregate, PropertyPathInterface
return;
}
if (!is_string($propertyPath)) {
throw new UnexpectedTypeException($propertyPath, 'string or Symfony\Component\PropertyAccess\PropertyPath');
throw new InvalidArgumentException(sprintf(
'The property path constructor needs a string or an instance of '.
'"Symfony\Component\PropertyAccess\PropertyPath". '.
'Got: "%s"',
is_object($propertyPath) ? get_class($propertyPath) : gettype($propertyPath)
));
}
if ('' === $propertyPath) {

View File

@ -139,6 +139,7 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
/**
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
* @expectedExceptionMessage PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "string" while trying to traverse path "foobar" at property "foobar".
*/
public function testGetValueThrowsExceptionIfNotObjectOrArray()
{
@ -147,6 +148,7 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
/**
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
* @expectedExceptionMessage PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "NULL" while trying to traverse path "foobar" at property "foobar".
*/
public function testGetValueThrowsExceptionIfNull()
{
@ -155,12 +157,22 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
/**
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
* @expectedExceptionMessage PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "string" while trying to traverse path "foobar" at property "foobar".
*/
public function testGetValueThrowsExceptionIfEmpty()
{
$this->propertyAccessor->getValue('', 'foobar');
}
/**
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
* @expectedExceptionMessage PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "NULL" while trying to traverse path "foobar.baz" at property "baz".
*/
public function testGetValueNestedExceptionMessage()
{
$this->propertyAccessor->getValue((object) array('foobar' => null), 'foobar.baz');
}
/**
* @dataProvider getValidPropertyPaths
*/
@ -249,6 +261,7 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
/**
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
* @expectedExceptionMessage PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "string" while trying to traverse path "foobar" at property "foobar".
*/
public function testSetValueThrowsExceptionIfNotObjectOrArray()
{
@ -259,6 +272,7 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
/**
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
* @expectedExceptionMessage PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "NULL" while trying to traverse path "foobar" at property "foobar".
*/
public function testSetValueThrowsExceptionIfNull()
{
@ -269,6 +283,7 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
/**
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
* @expectedExceptionMessage PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "string" while trying to traverse path "foobar" at property "foobar".
*/
public function testSetValueThrowsExceptionIfEmpty()
{
@ -277,6 +292,17 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
$this->propertyAccessor->setValue($value, 'foobar', 'bam');
}
/**
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
* @expectedExceptionMessage PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "NULL" while trying to traverse path "foobar.baz" at property "baz".
*/
public function testSetValueNestedExceptionMessage()
{
$value = (object) array('foobar' => null);
$this->propertyAccessor->setValue($value, 'foobar.baz', 'bam');
}
public function testGetValueWhenArrayValueIsNull()
{
$this->propertyAccessor = new PropertyAccessor(false, true);

View File

@ -69,7 +69,7 @@ class PropertyPathTest extends \PHPUnit_Framework_TestCase
}
/**
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
* @expectedException \Symfony\Component\PropertyAccess\Exception\InvalidArgumentException
*/
public function testPathCannotBeNull()
{
@ -77,7 +77,7 @@ class PropertyPathTest extends \PHPUnit_Framework_TestCase
}
/**
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
* @expectedException \Symfony\Component\PropertyAccess\Exception\InvalidArgumentException
*/
public function testPathCannotBeFalse()
{