@@ -92,32 +92,28 @@ private static function assertCountable($value, array $path, $method)
9292 private static function diffDeepWalk (array $ array , array $ array2 )
9393 {
9494 $ diff = array ();
95- $ allInt = true ;
96- \array_walk (
97- $ array ,
98- /**
99- * @param array-key $key
100- */
101- static function ($ value , $ key ) use (&$ allInt , &$ diff , $ array2 ) {
102- $ incl = false ;
103- if (\array_key_exists ($ key , $ array2 ) === false ) {
104- $ incl = true ;
105- } elseif (self ::isNonMergeable ($ value ) === false && self ::isNonMergeable ($ array2 [$ key ]) === false ) {
106- $ value = self ::diffDeep ($ value , $ array2 [$ key ]);
107- $ incl = !empty ($ value );
108- } elseif (\is_int ($ key )) {
109- $ foundIndex = \array_search ($ value , $ array2 , true );
110- $ incl = $ foundIndex === false || \is_int ($ foundIndex ) === false ;
111- } elseif ($ value !== $ array2 [$ key ]) {
112- // not in $array2 or different value
113- $ incl = true ;
114- }
115- if ($ incl ) {
116- $ allInt = $ allInt && \is_int ($ key );
117- $ diff [$ key ] = $ value ;
118- }
95+ $ allInt = true ; // true if all kept keys are int
96+ $ walkFunc = static function ($ value , $ key ) use (&$ allInt , &$ diff , $ array2 ) {
97+ $ incl = false ;
98+ if (\array_key_exists ($ key , $ array2 ) === false ) {
99+ $ incl = true ;
100+ } elseif (self ::isMergeable ($ value ) && self ::isMergeable ($ array2 [$ key ])) {
101+ $ value = self ::diffDeep ($ value , $ array2 [$ key ]);
102+ $ incl = !empty ($ value );
103+ } elseif (\is_int ($ key )) {
104+ // integer key... keep value if not in array2 (or if in array2, but with string key / not a list)
105+ $ foundIndex = \array_search ($ value , $ array2 , true );
106+ $ incl = $ foundIndex === false || \is_int ($ foundIndex ) === false ;
107+ } elseif ($ value !== $ array2 [$ key ]) {
108+ // different value in array2
109+ $ incl = true ;
119110 }
120- );
111+ if ($ incl ) {
112+ $ allInt = $ allInt && \is_int ($ key );
113+ $ diff [$ key ] = $ value ;
114+ }
115+ };
116+ \array_walk ($ array , $ walkFunc );
121117 if ($ allInt ) {
122118 $ diff = \array_values ($ diff );
123119 }
@@ -144,17 +140,17 @@ private static function diffStrictWalk(array $array, array $array2)
144140 }
145141
146142 /**
147- * Check that value is not an array
143+ * Check that value is an array (but not a "callable")
148144 *
149145 * @param mixed $value Value to test
150146 *
151147 * @return bool
152148 *
153- * @psalm-assert-if-false array $value
149+ * @psalm-assert-if-true array $value
154150 */
155- private static function isNonMergeable ($ value )
151+ private static function isMergeable ($ value )
156152 {
157- return \is_array ($ value ) === false || Php::isCallable ($ value , Php::IS_CALLABLE_ARRAY_ONLY );
153+ return \is_array ($ value ) && Php::isCallable ($ value , Php::IS_CALLABLE_ARRAY_ONLY ) === false ;
158154 }
159155
160156 /**
@@ -188,7 +184,7 @@ private static function mergeDeepWalk(array $arrayDef, array $array2)
188184 * @param array-key $key
189185 */
190186 static function ($ value , $ key ) use (&$ arrayDef ) {
191- if (self ::isNonMergeable ($ value )) {
187+ if (self ::isMergeable ($ value ) === false ) {
192188 // not array or appears to be a callable
193189 if (\is_int ($ key ) === false ) {
194190 $ arrayDef [$ key ] = $ value ;
@@ -198,7 +194,7 @@ static function ($value, $key) use (&$arrayDef) {
198194 }
199195 return ;
200196 }
201- if (isset ($ arrayDef [$ key ]) === false || self ::isNonMergeable ($ arrayDef [$ key ])) {
197+ if (isset ($ arrayDef [$ key ]) === false || self ::isMergeable ($ arrayDef [$ key ]) === false ) {
202198 // default not set or can be overwritten without merge
203199 $ arrayDef [$ key ] = $ value ;
204200 return ;
0 commit comments