diff --git a/src/Helpers.php b/src/Helpers.php index 6275a5d..82a316f 100644 --- a/src/Helpers.php +++ b/src/Helpers.php @@ -52,67 +52,4 @@ final class Helpers } return $result; } - - /** - * Проверяет идентичность двух классов - * - * @param object|string $class1 - * @param object|string $class2 - * @return bool - */ - public static function isSameClass(object|string $class1, object|string $class2): bool - { - return (is_object($class1) ? $class1::class : $class1) === (is_object($class2) ? $class2::class : $class2); - } - - /** - * Тестирует наследование класса (объекта) от указанных классов - * - * @param object|string $class Объект или имя класса для проверки - * @param string[] $parents Имена классов-родителей - * @see https://www.php.net/manual/ru/function.class-parents.php - */ - public static function checkExtendsClasses(object|string $class, array $parents): bool - { - return self::checkClassesIntersection($parents, $class, 'class_parents'); - } - - /** - * Тестирует имплементацию классом (объектом) указанных интерфейсов - * - * @param object|string $actual Объект или имя класса для проверки - * @param string[] $interfaces Имена классов-интерфейсов - * @see https://www.php.net/manual/ru/function.class-implements.php - */ - public static function checkImplementsInterfaces(object|string $actual, array $interfaces): bool - { - return self::checkClassesIntersection($interfaces, $actual, 'class_implements'); - } - - /** - * Тестирует использование классом (объектом) указанных трейтов - * - * @param object|string $class - * @param string[] $traits - * @return bool - * @see https://www.php.net/manual/ru/function.class-uses.php - */ - public static function checkUsesTraits(array $traits, object|string $class): bool - { - return self::checkClassesIntersection($traits, $class, 'class_uses'); - } - - /** - * Проверяет пересечение классов указанной функцией SPL - * - * @param object|string $class Класс для проверки на вхождение, или объект, класс коего нужно проверить - * @param string[] $classes Массив классов, вхождение в который нужно проверить - * @param string $function class_parents|class_implements|class_uses - */ - protected static function checkClassesIntersection(array $classes, object|string $class, string $function): bool - { - $actual_classes = is_object($class) ? $function($class) : [$class::class]; - return is_array($actual_classes) - && !empty(array_intersect($classes, $actual_classes)); - } } diff --git a/tests/AtolOnline/Tests/Api/KktMonitorTest.php b/tests/AtolOnline/Tests/Api/KktMonitorTest.php index f5ccfe5..a6d1c9d 100644 --- a/tests/AtolOnline/Tests/Api/KktMonitorTest.php +++ b/tests/AtolOnline/Tests/Api/KktMonitorTest.php @@ -57,7 +57,7 @@ class KktMonitorTest extends BasicTestCase $client = new KktMonitor(); $this->assertIsObject($client); $this->assertIsSameClass(KktMonitor::class, $client); - $this->assertExtendsClasses($client, [AtolClient::class]); + $this->assertExtendsClasses([AtolClient::class], $client); } /** @@ -78,7 +78,7 @@ class KktMonitorTest extends BasicTestCase $client = new KktMonitor(false, 'login', 'password', []); $this->assertIsObject($client); $this->assertIsSameClass($client, KktMonitor::class); - $this->assertExtendsClasses($client, [AtolClient::class]); + $this->assertExtendsClasses([AtolClient::class], $client); } /** diff --git a/tests/AtolOnline/Tests/BasicTestCase.php b/tests/AtolOnline/Tests/BasicTestCase.php index 3d1f26d..3e00662 100644 --- a/tests/AtolOnline/Tests/BasicTestCase.php +++ b/tests/AtolOnline/Tests/BasicTestCase.php @@ -81,60 +81,122 @@ class BasicTestCase extends TestCase } } + //------------------------------------------------------------------------------------------------------------------ + /** * Тестирует идентичность двух классов * - * @param object|string $expected - * @param object|string $actual + * @param object|string $expected Ожидаемый класс + * @param object|string $actual Фактический класс */ public function assertIsSameClass(object|string $expected, object|string $actual): void { - $this->assertTrue(Helpers::isSameClass($expected, $actual)); + $this->assertTrue($this->checkisSameClass($expected, $actual)); + } + + /** + * Проверяет идентичность двух классов + * + * @param object|string $class1 + * @param object|string $class2 + * @return bool + */ + private function checkisSameClass(object|string $class1, object|string $class2): bool + { + return (is_object($class1) ? $class1::class : $class1) + === (is_object($class2) ? $class2::class : $class2); } /** * Тестирует наследование класса (объекта) от указанных классов * - * @param object|string $class - * @param string[] $parents + * @param array $expected Массив ожидаемых имён классов-родителей + * @param object|string $actual Объект или имя класса для проверки */ - public function assertExtendsClasses(object|string $class, array $parents): void + public function assertExtendsClasses(array $expected, object|string $actual): void { - $this->assertTrue(Helpers::checkExtendsClasses($class, $parents)); + $this->assertTrue($this->checkExtendsClasses($expected, $actual)); + } + + /** + * Проверяет наследование класса (объекта) от указанных классов + * + * @param string[] $parents Имена классов-родителей + * @param object|string $class Объект или имя класса для проверки + */ + private function checkExtendsClasses(array $parents, object|string $class): bool + { + return !empty(array_intersect($parents, is_object($class) ? class_parents($class) : [$class])); } /** * Тестирует имплементацию классом (объектом) указанных интерфейсов * - * @param object|string $class - * @param string[] $interfaces + * @param string[] $expected Массив ожидаемых имён интерфейсов + * @param object|string $actual Объект или имя класса для проверки */ - public function assertImplementsInterfaces(object|string $class, array $interfaces): void + public function assertImplementsInterfaces(array $expected, object|string $actual): void { - $this->assertTrue(Helpers::checkImplementsInterfaces($class, $interfaces)); + $this->assertTrue($this->checkImplementsInterfaces($expected, $actual)); + } + + /** + * Проверяет имплементацию классом (объектом) указанных интерфейсов + * + * @param string[] $interfaces Имена классов-интерфейсов + * @param object|string $class Объект или имя класса для проверки + * @see https://www.php.net/manual/ru/function.class-implements.php + */ + private function checkImplementsInterfaces(array $interfaces, object|string $class): bool + { + return !empty(array_intersect($interfaces, is_object($class) ? class_implements($class) : [$class])); } /** * Тестирует использование классом (объектом) указанных трейтов * - * @param object|string $class - * @param string[] $traits + * @param string[] $expected Массив ожидаемых имён трейтов + * @param object|string $actual Объект или имя класса для проверки */ - public function assertUsesTraits(object|string $class, array $traits): void + public function assertUsesTraits(array $expected, object|string $actual): void { - $this->assertTrue(Helpers::checkUsesTraits($traits, $class)); + $this->assertTrue($this->checkUsesTraits($expected, $actual)); + } + + /** + * Проверяет использование классом (объектом) указанных трейтов (исключает родителей) + * + * @param string[] $traits Массив ожидаемых имён трейтов + * @param object|string $class Объект или имя класса для проверки + * @return bool + * @see https://www.php.net/manual/ru/function.class-uses.php#110752 + */ + private function checkUsesTraits(array $traits, object|string $class): bool + { + $found_traits = []; + $check_class = is_object($class) ? $class::class : $class; + do { + $found_traits = array_merge(class_uses($check_class, true), $found_traits); + } while ($check_class = get_parent_class($check_class)); + foreach ($found_traits as $trait => $same) { + $found_traits = array_merge(class_uses($trait, true), $found_traits); + } + return !empty(array_intersect(array_unique($found_traits), $traits)); } /** * Тестирует, является ли объект коллекцией * - * @param mixed $expected + * @param mixed $value */ - public function assertIsCollection(mixed $expected): void + public function assertIsCollection(mixed $value): void { - $this->assertIsObject($expected); - $this->assertIsIterable($expected); - $this->assertIsSameClass($expected, Collection::class); + $this->assertIsObject($value); + $this->assertIsIterable($value); + $this->assertTrue( + $this->checkisSameClass(Collection::class, $value) || + $this->checkExtendsClasses([Collection::class], $value) + ); } //------------------------------------------------------------------------------------------------------------------