From 64196613a1e351efea06553111bb18444f658547 Mon Sep 17 00:00:00 2001 From: Anton Date: Sat, 27 Aug 2022 15:57:21 +0300 Subject: [PATCH] Fix Comparator Adds `getType` and `canCompare` methods and fix `compare` method Signed-off-by: Anton --- src/Comparator.php | 88 ++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 38 deletions(-) diff --git a/src/Comparator.php b/src/Comparator.php index b6b57e6..1099315 100644 --- a/src/Comparator.php +++ b/src/Comparator.php @@ -5,25 +5,6 @@ use Closure; use ReflectionFunction; -use function abs; -use function array_keys; -use function count; -use function ksort; -use function get_class; -use function get_object_vars; -use function get_resource_type; -use function gettype; -use function in_array; -use function is_nan; -use function max; -use function method_exists; -use function min; -use function strcasecmp; -use function strcmp; -use function stream_get_meta_data; - -use const PHP_FLOAT_EPSILON; - /** * The flexible comparation. */ @@ -74,6 +55,17 @@ class Comparator */ public const EQUAL_STREAM = 256; + /** + * The alternative names of PHP types returning from `gettype()`. + */ + protected const ALT_TYPES = [ + 'NULL' => 'null', + 'boolean' => 'bool', + 'integer' => 'int', + 'double' => 'float', + 'resource (closed)' => 'resource', + ]; + /** * @var int The flags defines comparison behavior. */ @@ -121,6 +113,37 @@ public function hasFlag(int $flag): bool return ($this->flags & $flag) === $flag; } + /** + * Gets the PHP type of a variable. + * + * @param mixed $value the variable being type checked + * @return string the type name + */ + public function getType($value): string + { + $type = gettype($value); + + return static::ALT_TYPES[$type] ?? $type; + } + + /** + * Checks whether PHP types are comparable (non-strict comparison). + * + * @param string $type the first type name + * @param string $type2 the second type name + */ + public function canCompare(string $type, string $type2): bool + { + if ( + ($type === 'object' && in_array($type2, ['int', 'float'], true)) + || ($type2 === 'object' && in_array($type, ['int', 'float'], true)) + ) { + return false; + } + + return true; + } + /** * Compares two values. * @@ -132,31 +155,20 @@ public function compare($value, $value2): bool { if ($value === $value2) { return true; - } - - $type = gettype($value); - $type2 = gettype($value2); - if ($this->hasFlag(self::STRICT) && $type !== $type2) { + } elseif ($this->hasFlag(self::STRICT)) { return false; } - if ( - !$this->hasFlag(self::STRICT) - && $type === $type2 - && $type !== 'array' - && $value == $value2 - ) { + + $type = $this->getType($value); + $type2 = $this->gettype($value2); + + if ($this->canCompare($type, $type2) && $value == $value2) { return true; } - // TODO: fix non-strict comparation of non-compatible types (object with not object/string) - if ($type === 'double' || $type2 === 'double') { - $type = 'float'; - } elseif ($type === 'string' || $type2 === 'string') { - $type = 'string'; - } if ( - ($type === $type2 && in_array($type, ['array', 'object', 'resource'], true)) - || in_array($type, ['float', 'string'], true) + $type === $type2 + && in_array($type, ['array', 'object', 'resource', 'float', 'string'], true) ) { return $this->{'compare' . $type . 's'}($value, $value2); }