$value) { // Remove only if unchanged in the active state. if (isset($active[$key]) && $active[$key] === $previous[$key]) { unset($result[$key]); } } // Detect and handle additions. // Additions are keys added since the previous state and not overridden // in the active state. $added = array_diff_key($current, $previous, $active); // Merge in all current keys while retaining the key order. $merged = array_replace($current, $result); // Filter to keep array items from the merged set that ... $result = array_intersect_key( // Have keys that are either ... $merged, array_flip( array_merge( // In the original result set or ... array_keys($result), // Should be added. array_keys($added) ) ) ); // Detect and process changes. foreach ($current as $key => $value) { if (isset($previous[$key]) && $previous[$key] !== $value) { // If we have an array, recurse. if (is_array($value) && is_array($previous[$key]) && isset($active[$key]) && is_array($active[$key])) { $recursion_keys = $parent_keys; $recursion_keys[] = $key; $level++; $result[$key] = self::mergeConfigItemStates($previous[$key], $value, $active[$key], $recursion_keys, $level); } else { $operation = static::OPERATION_IGNORE; // Accept the new value only if the item hasn't been customized. if (isset($active[$key]) && $active[$key] === $previous[$key]) { $result[$key] = $value; $operation = static::OPERATION_UPDATE; } self::$logs[$operation][] = [ 'name' => $key, 'state' => [ 'active' => $active[$key], 'previous' => $previous[$key], 'new' => $value, ], 'parents' => $parent_keys, ]; } } } } // Process indexed arrays. Here we can't reliably distinguish between an // array value that's been changed and one that is new. Therefore, rather // than merging array values, we return either the active or the current // (new) state. else { $operation = static::OPERATION_IGNORE; // If the data is unchanged, use the current value. Otherwise, retain any // customization by keeping with the active value set above. if ($previous === $active) { $result = $current; $operation = static::OPERATION_SUBSTITUTE; } self::$logs[$operation][] = [ 'name' => end($parent_keys), 'state' => [ 'active' => $active, 'previous' => $previous, 'new' => $current, ], 'parents' => $parent_keys, ]; } return $result; } }