private static function isEqual($expected, $actual, $level = 0, $objects = NULL)
{
if ($level > 10) {
throw new \Exception('Nesting level too deep or recursive dependency.');
}
if (is_float($expected) && is_float($actual) && is_finite($expected) && is_finite($actual)) {
$diff = abs($expected - $actual);
return $diff < self::EPSILON || $diff / max(abs($expected), abs($actual)) < self::EPSILON;
}
if (is_object($expected) && is_object($actual) && get_class($expected) === get_class($actual)) {
$objects = $objects ? clone $objects : new \SplObjectStorage();
if (isset($objects[$expected])) {
return $objects[$expected] === $actual;
} elseif ($expected === $actual) {
return TRUE;
}
$objects[$expected] = $actual;
$objects[$actual] = $expected;
$expected = (array) $expected;
$actual = (array) $actual;
}
if (is_array($expected) && is_array($actual)) {
ksort($expected, SORT_STRING);
ksort($actual, SORT_STRING);
if (array_keys($expected) !== array_keys($actual)) {
return FALSE;
}
foreach ($expected as $value) {
if (!self::isEqual($value, current($actual), $level + 1, $objects)) {
return FALSE;
}
next($actual);
}
return TRUE;
}
return $expected === $actual;
}