$properties An array of properties and the merge strategy for them. * @param array $options The options to use when merging properties. * @return void */ protected function _mergeVars(array $properties, array $options = []): void { $class = static::class; $parents = []; while (true) { $parent = get_parent_class($class); if (!$parent) { break; } $parents[] = $parent; $class = $parent; } foreach ($properties as $property) { if (!property_exists($this, $property)) { continue; } $thisValue = $this->{$property}; if ($thisValue === null || $thisValue === false) { continue; } $this->_mergeProperty($property, $parents, $options); } } /** * Merge a single property with the values declared in all parent classes. * * @param string $property The name of the property being merged. * @param array $parentClasses An array of classes you want to merge with. * @param array $options Options for merging the property, see _mergeVars() * @return void */ protected function _mergeProperty(string $property, array $parentClasses, array $options): void { $thisValue = $this->{$property}; $isAssoc = false; if ( isset($options['associative']) && in_array($property, (array)$options['associative'], true) ) { $isAssoc = true; } if ($isAssoc) { $thisValue = Hash::normalize($thisValue); } foreach ($parentClasses as $class) { $parentProperties = get_class_vars($class); if (empty($parentProperties[$property])) { continue; } $parentProperty = $parentProperties[$property]; if (!is_array($parentProperty)) { continue; } $thisValue = $this->_mergePropertyData($thisValue, $parentProperty, $isAssoc); } $this->{$property} = $thisValue; } /** * Merge each of the keys in a property together. * * @param array $current The current merged value. * @param array $parent The parent class' value. * @param bool $isAssoc Whether the merging should be done in associative mode. * @return array The updated value. */ protected function _mergePropertyData(array $current, array $parent, bool $isAssoc) { if (!$isAssoc) { return array_merge($parent, $current); } $parent = Hash::normalize($parent); foreach ($parent as $key => $value) { if (!isset($current[$key])) { $current[$key] = $value; } } return $current; } }