From 1329eb6479f22e90588a2929314b0cffbb7edca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 9 Feb 2016 17:23:20 +0100 Subject: [PATCH 01/10] [PropertyAccess] Throw an InvalidArgumentException when the type do not match --- .../PropertyAccess/PropertyAccessor.php | 38 +++++++++++++++++-- .../Tests/Fixtures/TestClass.php | 11 ++++++ .../Tests/PropertyAccessorTest.php | 18 +++++++++ 3 files changed, 63 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 87e9c71266ef7..eb83bc5644714 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -12,6 +12,7 @@ namespace Symfony\Component\PropertyAccess; use Symfony\Component\PropertyAccess\Exception\AccessException; +use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException; use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException; use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException; @@ -553,7 +554,7 @@ private function writeProperty(&$object, $property, $value) $access = $this->getWriteAccessInfo($object, $property, $value); if (self::ACCESS_TYPE_METHOD === $access[self::ACCESS_TYPE]) { - $object->{$access[self::ACCESS_NAME]}($value); + $this->callMethod($object, $access[self::ACCESS_NAME], $value); } elseif (self::ACCESS_TYPE_PROPERTY === $access[self::ACCESS_TYPE]) { $object->{$access[self::ACCESS_NAME]} = $value; } elseif (self::ACCESS_TYPE_ADDER_AND_REMOVER === $access[self::ACCESS_TYPE]) { @@ -567,12 +568,41 @@ private function writeProperty(&$object, $property, $value) $object->$property = $value; } elseif (self::ACCESS_TYPE_MAGIC === $access[self::ACCESS_TYPE]) { - $object->{$access[self::ACCESS_NAME]}($value); + $this->callMethod($object, $access[self::ACCESS_NAME], $value); } else { throw new NoSuchPropertyException($access[self::ACCESS_NAME]); } } + /** + * Call a method and convert {@see \TypeError} to {@see InvalidArgumentException}. + * + * @param object $object + * @param string $method + * @param mixed $value + */ + private function callMethod($object, $method, $value) { + if (class_exists('TypeError')) { + // PHP 7 + try { + $object->{$method}($value); + } catch (\TypeError $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + } + + // PHP 5 + set_error_handler(function ($errno, $errstr) { + throw new InvalidArgumentException($errstr); + }); + + try { + $object->{$method}($value); + } finally { + restore_error_handler(); + } + } + /** * Adjusts a collection-valued property by calling add*() and remove*() * methods. @@ -613,11 +643,11 @@ private function writeCollection($object, $property, $collection, $addMethod, $r } foreach ($itemToRemove as $item) { - $object->{$removeMethod}($item); + $this->callMethod($object, $removeMethod, $item); } foreach ($itemsToAdd as $item) { - $object->{$addMethod}($item); + $this->callMethod($object, $addMethod, $item); } } diff --git a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClass.php b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClass.php index 7b1b927529afe..e63af3a8bac5d 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClass.php +++ b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClass.php @@ -26,6 +26,7 @@ class TestClass private $publicIsAccessor; private $publicHasAccessor; private $publicGetter; + private $date; public function __construct($value) { @@ -173,4 +174,14 @@ public function getPublicGetter() { return $this->publicGetter; } + + public function setDate(\DateTimeInterface $date) + { + $this->date = $date; + } + + public function getDate() + { + return $this->date; + } } diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index ce4438550e8d3..5cd31c4abccf3 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\PropertyAccess\Tests; +use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException; use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException; use Symfony\Component\PropertyAccess\PropertyAccessor; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClass; @@ -510,4 +511,21 @@ public function testIsWritableForReferenceChainIssue($object, $path, $value) { $this->assertEquals($value, $this->propertyAccessor->isWritable($object, $path)); } + + /** + * @expectedException InvalidArgumentException + */ + public function testConvertTypeErrorToInvalidArgumentException() + { + $this->propertyAccessor->setValue(new TestClass('Kévin'), 'date', 'This is a string, \DateTime excepted.'); + } + + public function testSetTypeHint() + { + $date = new \DateTimeImmutable(); + $object = new TestClass('Kévin'); + + $this->propertyAccessor->setValue($object, 'date', $date); + $this->assertSame($date, $object->getDate()); + } } From 762e5b181fe2bbbcd21421ba9f13223134486624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 9 Feb 2016 17:34:47 +0100 Subject: [PATCH 02/10] Add missing return statement. Update PHPDoc --- src/Symfony/Component/PropertyAccess/PropertyAccessor.php | 2 ++ .../Component/PropertyAccess/PropertyAccessorInterface.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index eb83bc5644714..3298277e04e1a 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -589,6 +589,8 @@ private function callMethod($object, $method, $value) { } catch (\TypeError $e) { throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); } + + return; } // PHP 5 diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessorInterface.php b/src/Symfony/Component/PropertyAccess/PropertyAccessorInterface.php index be41ee175d985..20198b9628f83 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessorInterface.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessorInterface.php @@ -43,7 +43,7 @@ interface PropertyAccessorInterface * @param string|PropertyPathInterface $propertyPath The property path to modify * @param mixed $value The value to set at the end of the property path * - * @throws Exception\InvalidArgumentException If the property path is invalid + * @throws Exception\InvalidArgumentException If the property path is invalid or the value type do not match with the setter type hint * @throws Exception\AccessException If a property/index does not exist or is not public * @throws Exception\UnexpectedTypeException If a value within the path is neither object * nor array From 90e7953cb31349d78ad4af645d347df5269fc6f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 16 Feb 2016 11:43:53 +0100 Subject: [PATCH 03/10] Fixes some edge cases... --- .../PropertyAccess/PropertyAccessor.php | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 3298277e04e1a..f7e22b327e08d 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -542,8 +542,9 @@ private function writeIndex(&$array, $index, $value) * @param string $property The property to write * @param mixed $value The value to write * - * @throws NoSuchPropertyException If the property does not exist or is not - * public. + * @throws NoSuchPropertyException If the property does not exist or is not + * public. + * @throws InvalidArgumentException */ private function writeProperty(&$object, $property, $value) { @@ -580,9 +581,13 @@ private function writeProperty(&$object, $property, $value) * @param object $object * @param string $method * @param mixed $value + * + * @throws InvalidArgumentException + * @throws \Exception */ private function callMethod($object, $method, $value) { - if (class_exists('TypeError')) { + // Cannot use class_exists because the PHP 7 polyfill defines \TypeError + if (PHP_MAJOR_VERSION >= 7) { // PHP 7 try { $object->{$method}($value); @@ -600,8 +605,12 @@ private function callMethod($object, $method, $value) { try { $object->{$method}($value); - } finally { restore_error_handler(); + } catch (\Exception $e) { + // Cannot use finally in 5.5 because of https://bugs.php.net/bug.php?id=67047 + restore_error_handler(); + + throw $e; } } @@ -614,6 +623,8 @@ private function callMethod($object, $method, $value) { * @param array|\Traversable $collection The collection to write * @param string $addMethod The add*() method * @param string $removeMethod The remove*() method + * + * @throws InvalidArgumentException */ private function writeCollection($object, $property, $collection, $addMethod, $removeMethod) { From 834f97030c0c4d3825d2168c02adcbb35c5175a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 16 Feb 2016 21:12:58 +0100 Subject: [PATCH 04/10] Test E_RECOVERABLE_ERROR --- src/Symfony/Component/PropertyAccess/PropertyAccessor.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index f7e22b327e08d..1664f1f238f05 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -600,7 +600,11 @@ private function callMethod($object, $method, $value) { // PHP 5 set_error_handler(function ($errno, $errstr) { - throw new InvalidArgumentException($errstr); + if (E_RECOVERABLE_ERROR === $errno) { + throw new InvalidArgumentException($errstr); + } + + return false; }); try { From bd210f90598cd002cdfae78ff187ce73699ef26b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 16 Feb 2016 21:14:23 +0100 Subject: [PATCH 05/10] Fix typo --- .../Component/PropertyAccess/PropertyAccessorInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessorInterface.php b/src/Symfony/Component/PropertyAccess/PropertyAccessorInterface.php index 20198b9628f83..ac4c2422b5445 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessorInterface.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessorInterface.php @@ -43,7 +43,7 @@ interface PropertyAccessorInterface * @param string|PropertyPathInterface $propertyPath The property path to modify * @param mixed $value The value to set at the end of the property path * - * @throws Exception\InvalidArgumentException If the property path is invalid or the value type do not match with the setter type hint + * @throws Exception\InvalidArgumentException If the property path is invalid or the value type does not match with the setter type hint * @throws Exception\AccessException If a property/index does not exist or is not public * @throws Exception\UnexpectedTypeException If a value within the path is neither object * nor array From 799ab295fcbec93e791d8102661d5111fc08c2be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 23 Feb 2016 17:40:08 +0100 Subject: [PATCH 06/10] Emulate PHP 7's \TypeError --- .../PropertyAccess/PropertyAccessor.php | 17 +++++------------ .../Tests/PropertyAccessorTest.php | 2 +- .../Component/PropertyAccess/composer.json | 3 ++- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 1664f1f238f05..e99e4d77493ff 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -586,22 +586,15 @@ private function writeProperty(&$object, $property, $value) * @throws \Exception */ private function callMethod($object, $method, $value) { - // Cannot use class_exists because the PHP 7 polyfill defines \TypeError if (PHP_MAJOR_VERSION >= 7) { - // PHP 7 - try { - $object->{$method}($value); - } catch (\TypeError $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - + $object->{$method}($value); return; } - // PHP 5 - set_error_handler(function ($errno, $errstr) { - if (E_RECOVERABLE_ERROR === $errno) { - throw new InvalidArgumentException($errstr); + // Emulates PHP 7 behavior + set_error_handler(function ($errno, $errstr) use ($object, $method) { + if (E_RECOVERABLE_ERROR === $errno && false !== strpos($errstr, sprintf('passed to %s::%s() must', get_class($object), $method))) { + throw new \TypeError($errstr); } return false; diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index 5cd31c4abccf3..0c671ef06d2d7 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -513,7 +513,7 @@ public function testIsWritableForReferenceChainIssue($object, $path, $value) } /** - * @expectedException InvalidArgumentException + * @expectedException \TypeError */ public function testConvertTypeErrorToInvalidArgumentException() { diff --git a/src/Symfony/Component/PropertyAccess/composer.json b/src/Symfony/Component/PropertyAccess/composer.json index fc657c1d21f9f..2cecd9c133071 100644 --- a/src/Symfony/Component/PropertyAccess/composer.json +++ b/src/Symfony/Component/PropertyAccess/composer.json @@ -16,7 +16,8 @@ } ], "require": { - "php": ">=5.5.9" + "php": ">=5.5.9", + "symfony/polyfill-php70": "~1.0" }, "autoload": { "psr-4": { "Symfony\\Component\\PropertyAccess\\": "" }, From 7233f7002f449cca1c50c4914dd5d57f72954fa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 23 Feb 2016 17:42:11 +0100 Subject: [PATCH 07/10] CS --- src/Symfony/Component/PropertyAccess/PropertyAccessor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index e99e4d77493ff..eea7db4b96402 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -12,7 +12,6 @@ namespace Symfony\Component\PropertyAccess; use Symfony\Component\PropertyAccess\Exception\AccessException; -use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException; use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException; use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException; @@ -588,6 +587,7 @@ private function writeProperty(&$object, $property, $value) private function callMethod($object, $method, $value) { if (PHP_MAJOR_VERSION >= 7) { $object->{$method}($value); + return; } From 453cc12d94d31cdfb183c1dfa33e48ce203060e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 23 Feb 2016 17:44:19 +0100 Subject: [PATCH 08/10] PHPDoc --- src/Symfony/Component/PropertyAccess/PropertyAccessor.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index eea7db4b96402..35d925d862fb7 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -543,7 +543,7 @@ private function writeIndex(&$array, $index, $value) * * @throws NoSuchPropertyException If the property does not exist or is not * public. - * @throws InvalidArgumentException + * @throws \TypeError */ private function writeProperty(&$object, $property, $value) { @@ -575,13 +575,13 @@ private function writeProperty(&$object, $property, $value) } /** - * Call a method and convert {@see \TypeError} to {@see InvalidArgumentException}. + * Emulates PHP 7 behavior in PHP 5. * * @param object $object * @param string $method * @param mixed $value * - * @throws InvalidArgumentException + * @throws \TypeError * @throws \Exception */ private function callMethod($object, $method, $value) { @@ -621,7 +621,7 @@ private function callMethod($object, $method, $value) { * @param string $addMethod The add*() method * @param string $removeMethod The remove*() method * - * @throws InvalidArgumentException + * @throws \TypeError */ private function writeCollection($object, $property, $collection, $addMethod, $removeMethod) { From fe8e9e5fa7c8763c828cc602eb7d867cf6719ef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 23 Feb 2016 17:54:59 +0100 Subject: [PATCH 09/10] More CS fixes --- .../Component/PropertyAccess/PropertyAccessorInterface.php | 4 +++- .../Component/PropertyAccess/Tests/PropertyAccessorTest.php | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessorInterface.php b/src/Symfony/Component/PropertyAccess/PropertyAccessorInterface.php index ac4c2422b5445..5def1f4555cd2 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessorInterface.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessorInterface.php @@ -43,10 +43,12 @@ interface PropertyAccessorInterface * @param string|PropertyPathInterface $propertyPath The property path to modify * @param mixed $value The value to set at the end of the property path * - * @throws Exception\InvalidArgumentException If the property path is invalid or the value type does not match with the setter type hint + * @throws Exception\InvalidArgumentException If the property path is invalid * @throws Exception\AccessException If a property/index does not exist or is not public * @throws Exception\UnexpectedTypeException If a value within the path is neither object * nor array + * @throws \TypeError If a the type of the value does not match the type + * of the parameter of the mutator method */ public function setValue(&$objectOrArray, $propertyPath, $value); diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index 0c671ef06d2d7..f2ab76d1cdff5 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -11,7 +11,6 @@ namespace Symfony\Component\PropertyAccess\Tests; -use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException; use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException; use Symfony\Component\PropertyAccess\PropertyAccessor; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClass; @@ -515,7 +514,7 @@ public function testIsWritableForReferenceChainIssue($object, $path, $value) /** * @expectedException \TypeError */ - public function testConvertTypeErrorToInvalidArgumentException() + public function testThrowTypeError() { $this->propertyAccessor->setValue(new TestClass('Kévin'), 'date', 'This is a string, \DateTime excepted.'); } From 28dc4e3d4825fc5e9d66097f7463bfadaa267ed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 23 Feb 2016 17:57:28 +0100 Subject: [PATCH 10/10] CS --- src/Symfony/Component/PropertyAccess/PropertyAccessor.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 35d925d862fb7..38f9afb7ad442 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -541,8 +541,8 @@ private function writeIndex(&$array, $index, $value) * @param string $property The property to write * @param mixed $value The value to write * - * @throws NoSuchPropertyException If the property does not exist or is not - * public. + * @throws NoSuchPropertyException If the property does not exist or is not + * public. * @throws \TypeError */ private function writeProperty(&$object, $property, $value) @@ -575,7 +575,7 @@ private function writeProperty(&$object, $property, $value) } /** - * Emulates PHP 7 behavior in PHP 5. + * Throws a {@see \TypeError} as in PHP 7 when using PHP 5. * * @param object $object * @param string $method @@ -591,7 +591,6 @@ private function callMethod($object, $method, $value) { return; } - // Emulates PHP 7 behavior set_error_handler(function ($errno, $errstr) use ($object, $method) { if (E_RECOVERABLE_ERROR === $errno && false !== strpos($errstr, sprintf('passed to %s::%s() must', get_class($object), $method))) { throw new \TypeError($errstr); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy