Skip to content

Instantly share code, notes, and snippets.

@jubianchi
Last active August 29, 2015 14:26
Show Gist options
  • Save jubianchi/fdab743caba66f1b1a89 to your computer and use it in GitHub Desktop.
Save jubianchi/fdab743caba66f1b1a89 to your computer and use it in GitHub Desktop.
<?php
function getIdentity($mixed)
{
return md5(serialize(cleanClosures($mixed)));
}
function cleanClosures($mixed)
{
$values = array();
if (is_object($mixed))
{
$reflection = new \reflectionObject($mixed);
foreach ($reflection->getProperties() as $property)
{
$access = $property->isPublic();
$property->setAccessible(true);
$value = $property->getValue($mixed);
$values[] = $value;
$property->setAccessible($access);
}
}
else
{
$values = $mixed;
}
return array_map(
function($value) use (& $identity)
{
if (is_array($value))
{
return cleanClosures($value);
}
if ($value instanceof \closure)
{
return spl_object_hash($value);
}
return $value;
},
$values
);
}
function toArray($mixed, & $identities = array(), & $recusrsion = false)
{
if (@json_encode($mixed))
{
return $mixed;
}
if (is_array($mixed))
{
return cleanClosures($mixed);
}
$identity = getIdentity($mixed);
if (in_array($identity, $identities))
{
$recusrsion = true;
return (object) $identity;
}
$identities[] = $identity;
$properties = array();
$reflection = new \reflectionObject($mixed);
foreach ($reflection->getProperties() as $property)
{
$access = $property->isPublic();
$property->setAccessible(true);
$value = $property->getValue($mixed);
if (is_object($value))
{
$value = toArray($value, $identities, $recusrsion);
}
if (is_array($value))
{
$value = toArray($value, $identities, $recusrsion);
}
$properties[$property->getName()] = $value;
$property->setAccessible($access);
}
if ($recusrsion === false)
{
return $mixed;
}
return (object) $properties;
}
function compare($title, $a, $b, $expect)
{
$identities = array(getIdentity($b));
$toArrayA = toArray($a, $identities);
$identities = array(getIdentity($a));
$toArrayB = toArray($b, $identities);
$result = $toArrayA == $toArrayB;
echo $title . ' - Should be ' . var_export($expect, true) . ': ' . var_export($result, true);
if ($result !== $expect) {
echo PHP_EOL . 'a: ' . var_export($toArrayA, true);
echo PHP_EOL . 'b: ' . var_export($toArrayB, true);
} else {
echo ' \o/';
}
echo PHP_EOL . str_repeat('-', 30) . PHP_EOL;
}
compare('A', new stdClass, new stdClass, true);
$object = new \stdClass;
$otherObject = new \stdClass;
$childObject = new \stdClass;
$otherChildObject = new \stdClass;
$childObject->property = $object;
$otherChildObject->property = $object;
$object->child = $childObject;
$otherObject->child = $otherChildObject;
compare('B', $object, $otherObject, true);
$object = new \stdClass;
$otherObject = new \stdClass;
$childObject = new \stdClass;
$otherChildObject = new \stdClass;
$childObject->property = $object;
$otherChildObject->property = $object;
$object->child = $childObject;
$otherObject->child = $childObject;
compare('C', $object, $otherObject, true);
class foo
{
public $str;
public $bar;
public function __construct($str)
{
$this->str = $str;
}
}
class bar
{
public $foo;
public function __construct($foo)
{
$this->foo = $foo;
}
}
$object = new foo('ok');
$object->bar = new bar($object);
$otherObject = new foo('ok');
$otherObject->bar = new bar($otherObject);
compare('D', $object, $object, true);
compare('D', $otherObject, $otherObject, true);
compare('E', $object, $otherObject, true);
$object = new foo('ok');
$object->bar = new bar(new stdClass);
$otherObject = new foo('ok');
$otherObject->bar = new bar(new stdClass);
compare('F', $object, $otherObject, true);
$object = new foo('ok');
$object->bar = new bar($object);
$otherObject = new foo('ko');
$otherObject->bar = new bar($otherObject);
compare('G', $object, $object, true);
compare('H', $otherObject, $otherObject, true);
compare('I', $object, $otherObject, false);
require_once __DIR__ . '/classes/autoloader.php';
class test extends mageekguy\atoum\test {}
compare('J', new test, new test, false);
$a = new stdClass;
$a->property = array(function() {});
$b = new stdClass;
$b->property = array(function() {});
compare('K', $a, $b, false);
$object = new stdClass;
$object->str = 'foo';
$otherObject = new foo('foo');
compare('L', $object, $otherObject, false);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment