Skip to content
Permalink
Browse files

Extract mergeVars into a trait.

MergeVariablesTrait walks the entire inheritance tree.  This provides
a more consistent and predictable behavior in comparions to
Object::_mergeVars() which skips classes almost at random in the
inheritance tree.
  • Loading branch information...
markstory committed Oct 9, 2012
1 parent daf3e7a commit 35641cdc70a65aaeccc64da493bbe2d18c769683
@@ -0,0 +1,89 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 3.0.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace Cake\Test\TestCase\Utility;
use Cake\TestSuite\TestCase;
use Cake\Utility\MergeVariablesTrait;
class Base {
use MergeVariablesTrait;
public $listProperty = ['One'];
public $assocProperty = ['Red'];
public function mergeVars($properties) {
return $this->_mergeVars($properties);
}
}
class Child extends Base {
public $listProperty = ['Two', 'Three'];
public $assocProperty = [
'Green' => ['lime'],
'Orange'
];
}
class Grandchild extends Child {
public $listProperty = ['Four', 'Five'];
public $assocProperty = [
'Green' => ['apple'],
'Yellow' => ['banana']
];
}
/**
* MergeVariablesTrait test case
*
* @package Cake.Test.TestCase.Utility
*/
class MergeVariablesTraitTest extends TestCase {
/**
* Test merging vars as a list.
*
* @return void
*/
public function testMergeVarsAsList() {
$object = new Grandchild();
$object->mergeVars(['listProperty' => false]);
$expected = ['One', 'Two', 'Three', 'Four', 'Five'];
$this->assertSame($expected, $object->listProperty);
}
/**
* Test merging vars as an assoc list.
*
* @return void
*/
public function testMergeVarsAsAssoc() {
$object = new Grandchild();
$object->mergeVars(['assocProperty' => true]);
$expected = [
'Red' => null,
'Orange' => null,
'Green' => ['lime', 'apple'],
'Yellow' => ['banana'],
];
$this->assertEquals($expected, $object->assocProperty);
}
}
@@ -0,0 +1,82 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 3.0.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace Cake\Utility;
use Cake\Utility\Hash;
/**
* Provides features for merging object properties recursively with
* parent classes.
*
* @package Cake.Utility
*/
trait MergeVariablesTrait {
/**
* Merge the list of $properties with all parent classes of the current class.
*
* @param array $properties An array of properties and the merge strategy for them.
* @return void
*/
protected function _mergeVars($properties) {
$class = get_class($this);
$parents = [];
while (true) {
$parent = get_parent_class($class);
if (!$parent) {
break;
}
$parents[] = $parent;
$class = $parent;
}
foreach ($properties as $property => $strategy) {
if (!property_exists($this, $property)) {
continue;
}
$thisValue = $this->{$property};
if ($thisValue === null || $thisValue === false) {
continue;
}
$this->_mergeProperty($property, $parents, $strategy);
}
}
/**
* 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 bool $asAssoc Set true for merging as assoc, false for list.
* @return void
*/
protected function _mergeProperty($property, $parentClasses, $asAssoc) {
$thisValue = $this->{$property};
if ($asAssoc) {
$thisValue = Hash::normalize($thisValue);
}
foreach ($parentClasses as $class) {
$parentProperties = get_class_vars($class);
if (!isset($parentProperties[$property])) {
continue;
}
$parentProperty = $parentProperties[$property];
if ($asAssoc) {
$parentProperty = Hash::normalize($parentProperty);
}
$thisValue = Hash::merge($parentProperty, $thisValue);
}
$this->{$property} = $thisValue;
}
}

0 comments on commit 35641cd

Please sign in to comment.
You can’t perform that action at this time.