Skip to content

Commit

Permalink
Merge pull request #8 from makasim/do-array-deep-copy-on-get-values-call
Browse files Browse the repository at this point in the history
do array deep copy on get_values call. Remove refs on sub arrays.
  • Loading branch information
makasim authored Oct 24, 2017
2 parents 0bfa737 + ccb0a80 commit 5a03e8b
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 8 deletions.
23 changes: 23 additions & 0 deletions src/functions/array.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,26 @@ function array_path_unset(array &$array, array $parents, &$keyExisted = null) {
$keyExisted = FALSE;
}
}

function array_copy(array $array)
{
// values array may contain sub array passed as a reference to a sub object.
// this code removes such refs from the array.
// Here's "foreach rec optimized" version which showed the best result
// performance results (1000 cycles):
// get_values - 0.001758
// foreach rec optimized - 0.008587
// foreach recursion - 0.015547
// serialize\unserialze - 0.020816
// json encode\decode - 0.078953
$copiedArray = [];
foreach($array as $key => $value) {
if(is_array($value)) {
$value = array_copy($value);
}

$copiedArray[$key] = $value;
}

return $copiedArray;
}
6 changes: 3 additions & 3 deletions src/functions/objects.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function set_object($context, $key, $object)
(function($key, $object) use($context) {
if ($object) {
set_value($this, $key, null);
set_value($this, $key, get_values($object));
set_value($this, $key, get_values($object, false));

$values =& array_get($key, [], $this->values);
set_values($object, $values, true);
Expand Down Expand Up @@ -41,7 +41,7 @@ function set_objects($context, $key, $objects)

$objectsValues = [];
foreach ($objects as $objectKey => $object) {
array_set($objectKey, get_values($object), $objectsValues);
array_set($objectKey, get_values($object, false), $objectsValues);
}

set_value($this, $key, $objectsValues);
Expand Down Expand Up @@ -71,7 +71,7 @@ function set_objects($context, $key, $objects)
function add_object($context, $key, $object, $objectKey = null)
{
(function($key, $object, $objectKey) use ($context) {
$objectValues = get_values($object);
$objectValues = get_values($object, false);

$objectKey = add_value($this, $key, $objectValues, $objectKey);

Expand Down
12 changes: 7 additions & 5 deletions src/functions/values.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*
* @return object
*/
function set_values($object, array &$values, $byReference = false)
function set_values($object, array &$values, bool $byReference = false)
{
$func = (function (array &$values, $byReference) {
if ($byReference) {
Expand All @@ -27,9 +27,11 @@ function set_values($object, array &$values, $byReference = false)
return $func($values, $byReference);
}

function get_values($object)
function get_values($object, bool $copy = true): array
{
return (function () { return $this->values; })->call($object);
$values = (function () { return $this->values; })->call($object);

return $copy ? array_copy($values) : $values;
}

function add_value($object, $key, $value, $valueKey = null)
Expand Down Expand Up @@ -178,7 +180,7 @@ function build_object_ref($classOrCallable = null, array &$values, $context = nu
$object = new $class();

//values set in constructor
$defaultValues = get_values($object);
$defaultValues = get_values($object, false);
$values = array_replace($defaultValues, $values);

set_values($object, $values, true);
Expand Down Expand Up @@ -209,7 +211,7 @@ function build_object($classOrCallable = null, array $values)

function clone_object($object)
{
return build_object(get_class($object), get_values($object));
return build_object(get_class($object), get_values($object, true));
}

function register_cast_hooks($objectOrClass = null) {
Expand Down
19 changes: 19 additions & 0 deletions tests/ObjectsTraitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -691,4 +691,23 @@ public function testClassProvidedByHookShouldTakePriorityOverClassAsArgument()

$this->assertInstanceOf($hookClass, $subObj);
}

public function testShouldNotChangeObjectValuesIfGetValuesCopiedTrue()
{
$subObj = new SubObject();
$subObj->setValue('aSubName.aSubKey', 'aFooVal');

$obj = new Object();
$obj->setObject('aName.aKey', $subObj);

$values = get_values($obj); // copy must be true by default

self::assertSame(['aName' => ['aKey' => ['aSubName' => ['aSubKey' => 'aFooVal']]]], get_values($obj));
self::assertSame(['aSubName' => ['aSubKey' => 'aFooVal']], get_values($subObj));

$values['aName']['aKey']['aSubName']['aSubKey'] = 'aBarVal';

self::assertSame(['aName' => ['aKey' => ['aSubName' => ['aSubKey' => 'aFooVal']]]], get_values($obj));
self::assertSame(['aSubName' => ['aSubKey' => 'aFooVal']], get_values($subObj));
}
}

0 comments on commit 5a03e8b

Please sign in to comment.