55use Closure ;
66use ReflectionFunction ;
77
8- use function abs ;
9- use function array_keys ;
10- use function count ;
11- use function ksort ;
12- use function get_class ;
13- use function get_object_vars ;
14- use function get_resource_type ;
15- use function gettype ;
16- use function in_array ;
17- use function is_nan ;
18- use function max ;
19- use function method_exists ;
20- use function min ;
21- use function strcasecmp ;
22- use function strcmp ;
23- use function stream_get_meta_data ;
24-
25- use const PHP_FLOAT_EPSILON ;
26-
278/**
289 * The flexible comparation.
2910 */
@@ -74,6 +55,17 @@ class Comparator
7455 */
7556 public const EQUAL_STREAM = 256 ;
7657
58+ /**
59+ * The alternative names of PHP types returning from `gettype()`.
60+ */
61+ protected const ALT_TYPES = [
62+ 'NULL ' => 'null ' ,
63+ 'boolean ' => 'bool ' ,
64+ 'integer ' => 'int ' ,
65+ 'double ' => 'float ' ,
66+ 'resource (closed) ' => 'resource ' ,
67+ ];
68+
7769 /**
7870 * @var int The flags defines comparison behavior.
7971 */
@@ -121,6 +113,37 @@ public function hasFlag(int $flag): bool
121113 return ($ this ->flags & $ flag ) === $ flag ;
122114 }
123115
116+ /**
117+ * Gets the PHP type of a variable.
118+ *
119+ * @param mixed $value the variable being type checked
120+ * @return string the type name
121+ */
122+ public function getType ($ value ): string
123+ {
124+ $ type = gettype ($ value );
125+
126+ return static ::ALT_TYPES [$ type ] ?? $ type ;
127+ }
128+
129+ /**
130+ * Checks whether PHP types are comparable (non-strict comparison).
131+ *
132+ * @param string $type the first type name
133+ * @param string $type2 the second type name
134+ */
135+ public function canCompare (string $ type , string $ type2 ): bool
136+ {
137+ if (
138+ ($ type === 'object ' && in_array ($ type2 , ['int ' , 'float ' ], true ))
139+ || ($ type2 === 'object ' && in_array ($ type , ['int ' , 'float ' ], true ))
140+ ) {
141+ return false ;
142+ }
143+
144+ return true ;
145+ }
146+
124147 /**
125148 * Compares two values.
126149 *
@@ -132,31 +155,20 @@ public function compare($value, $value2): bool
132155 {
133156 if ($ value === $ value2 ) {
134157 return true ;
135- }
136-
137- $ type = gettype ($ value );
138- $ type2 = gettype ($ value2 );
139- if ($ this ->hasFlag (self ::STRICT ) && $ type !== $ type2 ) {
158+ } elseif ($ this ->hasFlag (self ::STRICT )) {
140159 return false ;
141160 }
142- if (
143- !$ this ->hasFlag (self ::STRICT )
144- && $ type === $ type2
145- && $ type !== 'array '
146- && $ value == $ value2
147- ) {
161+
162+ $ type = $ this ->getType ($ value );
163+ $ type2 = $ this ->gettype ($ value2 );
164+
165+ if ($ this ->canCompare ($ type , $ type2 ) && $ value == $ value2 ) {
148166 return true ;
149167 }
150- // TODO: fix non-strict comparation of non-compatible types (object with not object/string)
151168
152- if ($ type === 'double ' || $ type2 === 'double ' ) {
153- $ type = 'float ' ;
154- } elseif ($ type === 'string ' || $ type2 === 'string ' ) {
155- $ type = 'string ' ;
156- }
157169 if (
158- ( $ type === $ type2 && in_array ( $ type , [ ' array ' , ' object ' , ' resource ' ], true ))
159- || in_array ($ type , ['float ' , 'string ' ], true )
170+ $ type === $ type2
171+ && in_array ($ type , [' array ' , ' object ' , ' resource ' , 'float ' , 'string ' ], true )
160172 ) {
161173 return $ this ->{'compare ' . $ type . 's ' }($ value , $ value2 );
162174 }
0 commit comments