Created
February 6, 2015 08:59
-
-
Save almadomundo/0ec0dce7f5435368aec0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Comparator | |
{ | |
public static function compareEntities($entityX, $entityY, array $exclusion = []) | |
{ | |
if (is_object($entityX) && is_object($entityY)) { | |
return self::checkObjectsEquals($entityX, $entityY, $exclusion); | |
} | |
if (is_array($entityX) && is_array($entityY)) { | |
return self::checkArraysEquals($entityX, $entityY, $exclusion); | |
} | |
return $entityX == $entityY; | |
} | |
public static function checkObjectsEquals($objectX, $objectY, array $exclusion = []) | |
{ | |
if (!is_object($objectX) || !is_object($objectY)) { | |
return false; | |
} | |
return self::checkObjectsEqualsByReflection($objectX, $objectY, $exclusion); | |
} | |
public static function checkArraysEquals(array $arrayX, array $arrayY, array $exclusion = []) | |
{ | |
return self::checkArraysEqualsByReflection($arrayX, $arrayY, $exclusion); | |
} | |
private static function checkObjectsEqualsByReflection($objectX, $objectY, array $exclusion = [], array &$visitedObjectHashes = []) | |
{ | |
if (get_class($objectX) != get_class($objectY)) { | |
return false; | |
} | |
$visitedObjectHashes[] = self::getObjectHash($objectX); | |
$visitedObjectHashes[] = self::getObjectHash($objectY); | |
$reflectionX = new \ReflectionObject($objectX); | |
$reflectionY = new \ReflectionObject($objectY); | |
if (count($reflectionX->getProperties()) != count($reflectionY->getProperties())) { | |
return false; | |
} | |
foreach ($reflectionX->getProperties() as $property) { | |
$property->setAccessible(true); | |
if (!$reflectionY->hasProperty($property->getName())) { | |
return false; | |
} | |
if (!in_array($property->getName(), $exclusion)) { | |
$entityX = $property->getValue($objectX); | |
$entityY = $property->getValue($objectY); | |
if (!($type = self::getPairType($entityX, $entityY))) { | |
return false; | |
} | |
switch ($type) { | |
case 'object' : | |
$alreadyVisited = array_intersect([self::getObjectHash($entityX), self::getObjectHash($entityY)], $visitedObjectHashes); | |
if (!$alreadyVisited && !self::checkObjectsEqualsByReflection($entityX, $entityY, $exclusion, $visitedObjectHashes)) { | |
return false; | |
} | |
break; | |
case 'array' : | |
if (!self::checkArraysEqualsByReflection($entityX, $entityY, $exclusion, $visitedObjectHashes)) { | |
return false; | |
} | |
break; | |
default : | |
if ($entityX != $entityY) { | |
return false; | |
} | |
break; | |
} | |
} | |
} | |
return true; | |
} | |
private static function checkArraysEqualsByReflection(array $arrayX, array $arrayY, array $exclusion = [], array &$visitedObjectHashes = []) | |
{ | |
if (count($arrayX) != count($arrayY)) { | |
return false; | |
} | |
$entityY = current($arrayY); | |
foreach ($arrayX as $entityX) { | |
if (!($type = self::getPairType($entityX, $entityY))) { | |
return false; | |
} | |
switch ($type) { | |
case 'object' : | |
$alreadyVisited = array_intersect([self::getObjectHash($entityX), self::getObjectHash($entityY)], $visitedObjectHashes); | |
if (!$alreadyVisited && !self::checkObjectsEqualsByReflection($entityX, $entityY, $exclusion, $visitedObjectHashes)) { | |
return false; | |
} | |
break; | |
case 'array' : | |
if (!self::checkArraysEqualsByReflection($entityX, $entityY, $exclusion, $visitedObjectHashes)) { | |
return false; | |
} | |
break; | |
default : | |
if ($entityX != $entityY) { | |
return false; | |
} | |
break; | |
} | |
$entityY = next($arrayY); | |
} | |
return true; | |
} | |
private static function getObjectHash($object) | |
{ | |
return spl_object_hash($object); | |
} | |
private static function getPairType($entityX, $entityY) | |
{ | |
if (gettype($entityX) != gettype($entityY)) { | |
return null; | |
} | |
return gettype($entityX); | |
} | |
} | |
class Foo | |
{ | |
private $holder; | |
private $children; | |
public function __construct($content = '', array $children = []) | |
{ | |
$this->holder = $content; | |
$this->setChildren($children); | |
} | |
public function setChildren(array $children) | |
{ | |
$this->children = $children; | |
foreach ($children as $child) { | |
$child->setParent($this); | |
} | |
} | |
} | |
class Bar | |
{ | |
private $holder; | |
private $parent; | |
public function __construct($content = '', Foo $parent = null) | |
{ | |
$this->holder = $content; | |
$this->setParent($parent); | |
} | |
public function setParent(Foo $parent = null) | |
{ | |
$this->parent = $parent; | |
} | |
} | |
$child0 = new Bar('child#0'); | |
$child1 = new Bar('child#1'); | |
//same | |
$child2 = new Bar('child#0'); | |
$child3 = new Bar('child#1'); | |
$parent0 = new Foo('parent', [$child0, $child1]); | |
$parent1 = new Foo('parent', [$child2, $child3]); | |
//Valid: | |
var_dump(Comparator::compareEntities($parent0, $parent1)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment