@@ -400,6 +400,7 @@ private function writeIndex(&$array, $index, $value)
400
400
*
401
401
* @throws NoSuchPropertyException If the property does not exist or is not
402
402
* public.
403
+ * @throws UnexpectedTypeException
403
404
*/
404
405
private function writeProperty (&$ object , $ property , $ singular , $ value )
405
406
{
@@ -410,7 +411,7 @@ private function writeProperty(&$object, $property, $singular, $value)
410
411
$ access = $ this ->getWriteAccessInfo ($ object , $ property , $ singular , $ value );
411
412
412
413
if (self ::ACCESS_TYPE_METHOD === $ access [self ::ACCESS_TYPE ]) {
413
- $ object ->{ $ access [self ::ACCESS_NAME ]}( $ value );
414
+ $ this -> callMethod ( $ object , $ access [self ::ACCESS_NAME ], $ value );
414
415
} elseif (self ::ACCESS_TYPE_PROPERTY === $ access [self ::ACCESS_TYPE ]) {
415
416
$ object ->{$ access [self ::ACCESS_NAME ]} = $ value ;
416
417
} elseif (self ::ACCESS_TYPE_ADDER_AND_REMOVER === $ access [self ::ACCESS_TYPE ]) {
@@ -457,12 +458,78 @@ private function writeProperty(&$object, $property, $singular, $value)
457
458
458
459
$ object ->$ property = $ value ;
459
460
} elseif (self ::ACCESS_TYP
10000
E_MAGIC === $ access [self ::ACCESS_TYPE ]) {
460
- $ object ->{ $ access [self ::ACCESS_NAME ]}( $ value );
461
+ $ this -> callMethod ( $ object , $ access [self ::ACCESS_NAME ], $ value );
461
462
} else {
462
463
throw new NoSuchPropertyException ($ access [self ::ACCESS_NAME ]);
463
464
}
464
465
}
465
466
467
+ /**
468
+ * Throws a {@see UnexpectedTypeException} as in PHP 7 when using PHP 5.
469
+ *
470
+ * @param object $object
471
+ * @param string $method
472
+ * @param mixed $value
473
+ *
474
+ * @throws UnexpectedTypeException
475
+ * @throws \Exception
476
+ */
477
+ private function callMethod ($ object , $ method , $ value ) {
478
+ if (PHP_MAJOR_VERSION >= 7 ) {
479
+ try {
480
+ $ object ->{$ method }($ value );
481
+ } catch (\TypeError $ e ) {
482
+ throw $ this ->createUnexpectedTypeException ($ object , $ method , $ value );
483
+ }
484
+
485
+ return ;
486
+ }
487
+
488
+ $ that = $ this ;
489
+ set_error_handler (function ($ errno , $ errstr ) use ($ object , $ method , $ value , $ that ) {
490
+ if (E_RECOVERABLE_ERROR === $ errno && false !== strpos ($ errstr , sprintf ('passed to %s::%s() must ' , get_class ($ object ), $ method ))) {
491
+ throw $ that ->createUnexpectedTypeException ($ object , $ method , $ value );
492
+ }
493
+
494
+ return false ;
495
+ });
496
+
497
+ try {
498
+ $ object ->{$ method }($ value );
499
+ restore_error_handler ();
500
+ } catch (\Exception $ e ) {
501
+ // Cannot use finally in 5.5 because of https://bugs.php.net/bug.php?id=67047
502
+ restore_error_handler ();
503
+
504
+ throw $ e ;
505
+ }
506
+ }
507
+
508
+ /**
509
+ * Creates an UnexpectedTypeException.
510
+ *
511
+ * @param object $object
512
+ * @param string $method
513
+ * @param mixed $value
514
+ *
515
+ * @return UnexpectedTypeException
516
+ */
517
+ private function createUnexpectedTypeException ($ object , $ method , $ value )
518
+ {
519
+ $ reflectionMethod = new \ReflectionMethod ($ object , $ method );
520
+ $ parameters = $ reflectionMethod ->getParameters ();
521
+
522
+ $ expectedType = 'unknown ' ;
523
+ if (isset ($ parameters [0 ])) {
524
+ $ class = $ parameters [0 ]->getClass ();
525
+ if (null !== $ class ) {
526
+ $ expectedType = $ class ->getName ();
527
+ }
528
+ }
529
+
530
+ return new UnexpectedTypeException ($ value , $ expectedType );
531
+ }
532
+
466
533
/**
467
534
* Guesses how to write the property value.
468
535
*
0 commit comments