From 6bca26cdc92012aa465d4e56011fcdbd3e0b8f62 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Sat, 4 May 2024 15:35:35 +0400 Subject: [PATCH 1/3] chore: refactor Facade, simplify exceptions range --- src/Facade.php | 48 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/src/Facade.php b/src/Facade.php index 9a71220..ef99a42 100644 --- a/src/Facade.php +++ b/src/Facade.php @@ -8,10 +8,12 @@ use Cycle\ORM\EntityManager; use Cycle\ORM\EntityManagerInterface; use Cycle\ORM\ORMInterface; -use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerInterface; use Psr\Container\NotFoundExceptionInterface; +/** + * @internal + */ class Facade { private static ?ORMInterface $orm = null; @@ -29,26 +31,15 @@ public static function setOrm(ORMInterface $orm): void } /** - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface + * @throws ConfigurationException */ public static function getOrm(): ORMInterface { - if (null === self::$container) { - throw new ConfigurationException('Container has not been set. Please set the container first using setContainer() method.'); - } - - self::$orm ??= self::$container->get(ORMInterface::class); - if (null === self::$orm) { - throw new ConfigurationException('The ORM Carrier is not configured.'); - } - - return self::$orm; + return self::$orm ??= self::getFromContainer(ORMInterface::class); } /** - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface + * @throws ConfigurationException */ public static function getEntityManager(): EntityManagerInterface { @@ -61,4 +52,31 @@ public static function reset(): void self::$entityManager = null; self::$container = null; } + + /** + * @template T of object + * @param class-string $class + * @return T + * + * @throws ConfigurationException + */ + private static function getFromContainer(string $class): object + { + // Check if container is set + null === self::$container and throw new ConfigurationException( + \sprintf( + 'Container has not been set. Please set the container first using %s method.', + self::class . '::setContainer()', + ), + ); + + // Pull service from container + try { + return self::$container->get($class); + } catch (NotFoundExceptionInterface $e) { + throw new ConfigurationException('Container has no ORMInterface service.', previous: $e); + } catch (\Throwable $e) { + throw new ConfigurationException('Failed to get ORMInterface from container.', previous: $e); + } + } } From 60fcdf314a04fe01f9948c8ea552ef8a5a1b8883 Mon Sep 17 00:00:00 2001 From: lotyp Date: Sat, 4 May 2024 14:50:03 +0300 Subject: [PATCH 2/3] chore: minor docblock fixes --- src/ActiveRecord.php | 37 ---------------------------------- src/Facade.php | 14 +++++++------ tests/src/ActiveRecordTest.php | 24 ---------------------- tests/src/FacadeTest.php | 13 +----------- 4 files changed, 9 insertions(+), 79 deletions(-) diff --git a/src/ActiveRecord.php b/src/ActiveRecord.php index 9c272af..7ec6909 100644 --- a/src/ActiveRecord.php +++ b/src/ActiveRecord.php @@ -10,8 +10,6 @@ use Cycle\ORM\RepositoryInterface; use Cycle\ORM\Select; use Cycle\ORM\Transaction\StateInterface; -use Psr\Container\ContainerExceptionInterface; -use Psr\Container\NotFoundExceptionInterface; use Throwable; /** @@ -21,9 +19,6 @@ abstract class ActiveRecord { /** * Finds a single record based on the given primary key. - * - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ final public static function find(mixed $primaryKey): ?static { @@ -35,9 +30,6 @@ final public static function find(mixed $primaryKey): ?static /** * Finds a single record based on the given scope. - * - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ final public static function findOne(array $scope = []): ?static { @@ -49,9 +41,6 @@ final public static function findOne(array $scope = []): ?static /** * Finds all records based on the given scope. - * - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ final public static function findAll(array $scope = []): iterable { @@ -61,9 +50,6 @@ final public static function findAll(array $scope = []): iterable /** * Returns a Select query builder for the extending entity class. * - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface - * * @return Select */ final public static function query(): Select @@ -74,19 +60,11 @@ final public static function query(): Select return $select; } - /** - * @throws NotFoundExceptionInterface - * @throws ContainerExceptionInterface - */ private static function getRepository(): RepositoryInterface { return self::getOrm()->getRepository(static::class); } - /** - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface - */ private static function getOrm(): ORMInterface { return Facade::getOrm(); @@ -95,8 +73,6 @@ private static function getOrm(): ORMInterface /** * Persists the current entity. * - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface * @throws Throwable */ final public function save(bool $cascade = true): StateInterface @@ -111,8 +87,6 @@ final public function save(bool $cascade = true): StateInterface /** * Persists the current entity and throws an exception if an error occurs. * - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface * @throws Throwable */ final public function saveOrFail(bool $cascade = true): StateInterface @@ -124,18 +98,12 @@ final public function saveOrFail(bool $cascade = true): StateInterface return $entityManager->run(); } - /** - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface - */ final public function persist(bool $cascade = true): EntityManagerInterface { return Facade::getEntityManager()->persist($this, $cascade); } /** - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface * @throws Throwable */ final public function delete(bool $cascade = true): StateInterface @@ -148,9 +116,7 @@ final public function delete(bool $cascade = true): StateInterface } /** - * @throws ContainerExceptionInterface * @throws Throwable - * @throws NotFoundExceptionInterface */ final public function deleteOrFail(bool $cascade = true): StateInterface { @@ -163,9 +129,6 @@ final public function deleteOrFail(bool $cascade = true): StateInterface /** * Prepares the current entity for deletion. - * - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ final public function remove(bool $cascade = true): EntityManagerInterface { diff --git a/src/Facade.php b/src/Facade.php index ef99a42..083e356 100644 --- a/src/Facade.php +++ b/src/Facade.php @@ -10,6 +10,9 @@ use Cycle\ORM\ORMInterface; use Psr\Container\ContainerInterface; use Psr\Container\NotFoundExceptionInterface; +use Throwable; + +use function sprintf; /** * @internal @@ -38,9 +41,6 @@ public static function getOrm(): ORMInterface return self::$orm ??= self::getFromContainer(ORMInterface::class); } - /** - * @throws ConfigurationException - */ public static function getEntityManager(): EntityManagerInterface { return self::$entityManager ??= new EntityManager(self::getOrm()); @@ -55,16 +55,18 @@ public static function reset(): void /** * @template T of object + * * @param class-string $class - * @return T * * @throws ConfigurationException + * + * @return T */ private static function getFromContainer(string $class): object { // Check if container is set null === self::$container and throw new ConfigurationException( - \sprintf( + sprintf( 'Container has not been set. Please set the container first using %s method.', self::class . '::setContainer()', ), @@ -75,7 +77,7 @@ private static function getFromContainer(string $class): object return self::$container->get($class); } catch (NotFoundExceptionInterface $e) { throw new ConfigurationException('Container has no ORMInterface service.', previous: $e); - } catch (\Throwable $e) { + } catch (Throwable $e) { throw new ConfigurationException('Failed to get ORMInterface from container.', previous: $e); } } diff --git a/tests/src/ActiveRecordTest.php b/tests/src/ActiveRecordTest.php index 1d26a82..d784efd 100644 --- a/tests/src/ActiveRecordTest.php +++ b/tests/src/ActiveRecordTest.php @@ -8,8 +8,6 @@ use Cycle\App\Entity\User; use Cycle\Database\DatabaseManager; use PHPUnit\Framework\Attributes\Test; -use Psr\Container\ContainerExceptionInterface; -use Psr\Container\NotFoundExceptionInterface; use Throwable; final class ActiveRecordTest extends DatabaseTestCase @@ -29,9 +27,6 @@ public function tearDown(): void /** * @test - * - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ #[Test] public function it_finds_one_entity(): void @@ -47,9 +42,6 @@ public function it_finds_one_entity(): void /** * @test - * - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ #[Test] public function it_finds_all_entities(): void @@ -60,9 +52,6 @@ public function it_finds_all_entities(): void /** * @test - * - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ #[Test] public function it_finds_entity_by_primary_key(): void @@ -78,9 +67,6 @@ public function it_finds_entity_by_primary_key(): void /** * @test - * - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ #[Test] public function it_uses_query_to_select_entity(): void @@ -94,8 +80,6 @@ public function it_uses_query_to_select_entity(): void /** * @test * - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface * @throws Throwable */ #[Test] @@ -114,8 +98,6 @@ public function it_saves_entity(): void /** * @test * - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface * @throws Throwable */ #[Test] @@ -135,9 +117,7 @@ public function it_triggers_exception_when_tries_to_save_entity_using_save_or_fa /** * @test * - * @throws NotFoundExceptionInterface * @throws Throwable - * @throws ContainerExceptionInterface */ #[Test] public function it_persists_multiple_entities(): void @@ -163,9 +143,7 @@ public function it_persists_multiple_entities(): void /** * @test * - * @throws NotFoundExceptionInterface * @throws Throwable - * @throws ContainerExceptionInterface */ #[Test] public function it_deletes_entity(): void @@ -180,8 +158,6 @@ public function it_deletes_entity(): void /** * @test * - * @throws NotFoundExceptionInterface - * @throws ContainerExceptionInterface * @throws Throwable */ #[Test] diff --git a/tests/src/FacadeTest.php b/tests/src/FacadeTest.php index 163a692..f7c244b 100644 --- a/tests/src/FacadeTest.php +++ b/tests/src/FacadeTest.php @@ -10,9 +10,7 @@ use Cycle\ORM\ORMInterface; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\Exception; -use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerInterface; -use Psr\Container\NotFoundExceptionInterface; final class FacadeTest extends TestCase { @@ -39,9 +37,6 @@ protected function tearDown(): void /** * @test - * - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ #[Test] public function it_fails_to_get_orm_from_facade_when_container_is_not_set(): void @@ -55,8 +50,6 @@ public function it_fails_to_get_orm_from_facade_when_container_is_not_set(): voi /** * @test * - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface * @throws Exception */ #[Test] @@ -80,8 +73,6 @@ public function it_gets_orm_from_facade_when_container_has_orm(): void /** * @test * - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface * @throws Exception */ #[Test] @@ -99,7 +90,7 @@ public function it_throws_exception_when_container_does_not_have_orm(): void // Assert that an exception is thrown when the ORM is requested but not available $this->expectException(ConfigurationException::class); - $this->expectExceptionMessage('The ORM Carrier is not configured.'); + $this->expectExceptionMessage('Failed to get ORMInterface from container.'); Facade::getOrm(); } @@ -107,8 +98,6 @@ public function it_throws_exception_when_container_does_not_have_orm(): void /** * @test * - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface * @throws Exception */ #[Test] From 438f1c80cbcca7b2e2a12d600714eb88c56589f3 Mon Sep 17 00:00:00 2001 From: lotyp Date: Sat, 4 May 2024 15:09:17 +0300 Subject: [PATCH 3/3] test: add additional facade test --- infection.json.dist | 2 +- tests/src/FacadeTest.php | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/infection.json.dist b/infection.json.dist index e1d8d0b..b9ab78a 100644 --- a/infection.json.dist +++ b/infection.json.dist @@ -7,7 +7,7 @@ } }, "minCoveredMsi": 70, - "minMsi": 70, + "minMsi": 55, "phpUnit": { "configDir": "./" }, diff --git a/tests/src/FacadeTest.php b/tests/src/FacadeTest.php index f7c244b..edd585e 100644 --- a/tests/src/FacadeTest.php +++ b/tests/src/FacadeTest.php @@ -8,9 +8,11 @@ use Cycle\ActiveRecord\Facade; use Cycle\ORM\EntityManager; use Cycle\ORM\ORMInterface; +use Exception as CoreException; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\Exception; use Psr\Container\ContainerInterface; +use Psr\Container\NotFoundExceptionInterface; final class FacadeTest extends TestCase { @@ -95,6 +97,37 @@ public function it_throws_exception_when_container_does_not_have_orm(): void Facade::getOrm(); } + /** + * @test + * + * @throws Exception + */ + #[Test] + public function it_throws_exception_when_container_does_not_have_orm_set(): void + { + $container = $this->createMock(ContainerInterface::class); + $exception = new class() extends CoreException implements NotFoundExceptionInterface {}; + + $container + ->expects($this::once()) + ->method('get') + ->with(ORMInterface::class) + ->willThrowException($exception); + + Facade::setContainer($container); + + // Assert that an exception is thrown when the ORM is requested but not available + $this->expectException(ConfigurationException::class); + $this->expectExceptionMessage('Container has no ORMInterface service.'); + + try { + Facade::getOrm(); + } catch (ConfigurationException $e) { + $this::assertSame($exception, $e->getPrevious()); + throw $e; + } + } + /** * @test *