-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[PropertyAccess] Throw an InvalidArgumentException when the type do not match #17738
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
1329eb6
762e5b1
90e7953
834f970
bd210f9
799ab29
7233f70
453cc12
fe8e9e5
28dc4e3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
…ot match
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry for disturbing.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I prefer to not test the error message. It's not clean and it still does not handle all cases. Throwing an error (and not an exception) in a mutator should be very very rare in a real code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What cases it does not handle? And it seems that message is same for all supported PHP 5 versions: https://3v4l.org/VZhkg There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A user can trigger an error with the same or a similar message. What do you think about that @symfony/deciders There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Users are not supposed to trigger errors with E_RECOVERABLE_ERROR type (there are specific ones with USER_...). So if there are other E_RECOVERABLE_ERROR errors that could be triggered by PHP here, we need to make sure only type errors are handled. |
||
throw new InvalidArgumentException($errstr); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why are you not checking for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea thanks |
||
}); | ||
|
||
try { | ||
$object->{$method}($value); | ||
} finally { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This may cause issues with PHP < 5.6 (a.k.a 5.5), which have a bugged implementation of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
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); | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{
should be on the next line