@@ -687,7 +687,8 @@ private function writeCollection($zval, $property, $collection, $addMethod, $rem
687
687
*/
688
688
private function getWriteAccessInfo ($ class , $ property , $ value )
689
689
{
690
- $ key = false !== strpbrk ($ key = $ class .'.. ' .$ property , '{}()/@: ' ) ? rawurlencode ($ key ) : $ key ;
690
+ $ useAdderAndRemover = \is_array ($ value ) || $ value instanceof \Traversable;
691
+ $ key = false !== strpbrk ($ key = $ class .'.. ' .$ property .'' .var_export ($ useAdderAndRemover , true ), '{}()/@: ' ) ? rawurlencode ($ key ) : $ key ;
691
692
692
693
if (isset ($ this ->writePropertyCache [$ key ])) {
693
694
return $ this ->writePropertyCache [$ key ];
@@ -707,6 +708,16 @@ private function getWriteAccessInfo($class, $property, $value)
707
708
$ camelized = $ this ->camelize ($ property );
708
709
$ singulars = (array ) Inflector::singularize ($ camelized );
709
710
711
+ if ($ useAdderAndRemover ) {
712
+ $ methods = $ this ->findAdderAndRemover ($ reflClass , $ singulars );
713
+
714
+ if (null !== $ methods ) {
715
+ $ access [self ::ACCESS_TYPE ] = self ::ACCESS_TYPE_ADDER_AND_REMOVER ;
716
+ $ access [self ::ACCESS_ADDER ] = $ methods [0 ];
717
+ $ access [self ::ACCESS_REMOVER ] = $ methods [1 ];
718
+ }
719
+ }
720
+
710
721
if (!isset ($ access [self ::ACCESS_TYPE ])) {
711
722
$ setter = 'set ' .$ camelized ;
712
723
$ getsetter = lcfirst ($ camelized ); // jQuery style, e.g. read: last(), write: last($item)
@@ -728,22 +739,16 @@ private function getWriteAccessInfo($class, $property, $value)
728
739
$ access [self ::ACCESS_TYPE ] = self ::ACCESS_TYPE_MAGIC ;
729
740
$ access [self ::ACCESS_NAME ] = $ setter ;
730
741
} elseif (null !== $ methods = $ this ->findAdderAndRemover ($ reflClass , $ singulars )) {
731
- if (\is_array ($ value ) || $ value instanceof \Traversable) {
732
- $ access [self ::ACCESS_TYPE ] = self ::ACCESS_TYPE_ADDER_AND_REMOVER ;
733
- $ access [self ::ACCESS_ADDER ] = $ methods [0 ];
734
- $ access [self ::ACCESS_REMOVER ] = $ methods [1 ];
735
- } else {
736
- $ access [self ::ACCESS_TYPE ] = self ::ACCESS_TYPE_NOT_FOUND ;
737
- $ access [self ::ACCESS_NAME ] = sprintf (
738
- 'The property "%s" in class "%s" can be defined with the methods "%s()" but ' .
739
- 'the new value must be an array or an instance of \Traversable, ' .
740
- '"%s" given. ' ,
741
- $ property ,
742
- $ reflClass ->name ,
743
- implode ('()", " ' , $ methods ),
744
- \is_object ($ value ) ? \get_class ($ value ) : \gettype ($ value )
745
- );
746
- }
742
+ $ access [self ::ACCESS_TYPE ] = self ::ACCESS_TYPE_NOT_FOUND ;
743
+ $ access [self ::ACCESS_NAME ] = sprintf (
744
+ 'The property "%s" in class "%s" can be defined with the methods "%s()" but ' .
745
+ 'the new value must be an array or an instance of \Traversable, ' .
746
+ '"%s" given. ' ,
747
+ $ property ,
748
+ $ reflClass ->name ,
749
+ implode ('()", " ' , $ methods ),
750
+ \is_object ($ value ) ? \get_class ($ value ) : \gettype ($ value )
751
+ );
747
752
} else {
748
753
$ access [self ::ACCESS_TYPE ] = self ::ACCESS_TYPE_NOT_FOUND ;
749
754
$ access [self ::ACCESS_NAME ] = sprintf (
@@ -783,6 +788,18 @@ private function isPropertyWritable($object, $property)
783
788
784
789
$ access = $ this ->getWriteAccessInfo (\get_class ($ object ), $ property , array ());
785
790
791
+ $ isWritable = self ::ACCESS_TYPE_METHOD === $ access [self ::ACCESS_TYPE ]
792
+ || self ::ACCESS_TYPE_PROPERTY === $ access [self ::ACCESS_TYPE ]
793
+ || self ::ACCESS_TYPE_ADDER_AND_REMOVER === $ access [self ::ACCESS_TYPE ]
794
+ || (!$ access [self ::ACCESS_HAS_PROPERTY ] && property_exists ($ object , $ property ))
795
+ || self ::ACCESS_TYPE_MAGIC === $ access [self ::ACCESS_TYPE ];
796
+
797
+ if ($ isWritable ) {
798
+ return true ;
799
+ }
800
+
801
+ $ access = $ this ->getWriteAccessInfo (\get_class ($ object ), $ property , '' );
802
+
786
803
return self ::ACCESS_TYPE_METHOD === $ access [self ::ACCESS_TYPE ]
787
804
|| self ::ACCESS_TYPE_PROPERTY === $ access [self ::ACCESS_TYPE ]
788
805
|| self ::ACCESS_TYPE_ADDER_AND_REMOVER === $ access [self ::ACCESS_TYPE ]
0 commit comments