init
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.0.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Utility;
|
||||
|
||||
/**
|
||||
* Provides features for merging object properties recursively with
|
||||
* parent classes.
|
||||
*/
|
||||
trait MergeVariablesTrait
|
||||
{
|
||||
/**
|
||||
* Merge the list of $properties with all parent classes of the current class.
|
||||
*
|
||||
* ### Options:
|
||||
*
|
||||
* - `associative` - A list of properties that should be treated as associative arrays.
|
||||
* Properties in this list will be passed through Hash::normalize() before merging.
|
||||
*
|
||||
* @param array<string> $properties An array of properties and the merge strategy for them.
|
||||
* @param array<string, mixed> $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<string> $parentClasses An array of classes you want to merge with.
|
||||
* @param array<string, mixed> $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): array
|
||||
{
|
||||
if (!$isAssoc) {
|
||||
return array_merge($parent, $current);
|
||||
}
|
||||
$parent = Hash::normalize($parent);
|
||||
foreach ($parent as $key => $value) {
|
||||
$current[$key] ??= $value;
|
||||
}
|
||||
|
||||
return $current;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user