Skip to content

Commit

Permalink
Merge pull request #16 from cycle/refactoring-facade
Browse files Browse the repository at this point in the history
chore: refactor Facade, simplify exceptions range
  • Loading branch information
lotyp authored May 4, 2024
2 parents c20aedb + 438f1c8 commit d8ef258
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 90 deletions.
2 changes: 1 addition & 1 deletion infection.json.dist
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
}
},
"minCoveredMsi": 70,
"minMsi": 70,
"minMsi": 55,
"phpUnit": {
"configDir": "./"
},
Expand Down
37 changes: 0 additions & 37 deletions src/ActiveRecord.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand All @@ -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
{
Expand All @@ -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
{
Expand All @@ -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
{
Expand All @@ -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<TEntity>
*/
final public static function query(): Select
Expand All @@ -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();
Expand All @@ -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

Check warning on line 78 in src/ActiveRecord.php

View workflow job for this annotation

GitHub Actions / mutation-testing (ubuntu-latest, 8.2, locked)

Escaped Mutant for Mutator "TrueValue": --- Original +++ New @@ @@ * * @throws Throwable */ - public final function save(bool $cascade = true) : StateInterface + public final function save(bool $cascade = false) : StateInterface { /** @var EntityManager $entityManager */ $entityManager = Facade::getEntityManager();
Expand All @@ -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

Check warning on line 92 in src/ActiveRecord.php

View workflow job for this annotation

GitHub Actions / mutation-testing (ubuntu-latest, 8.2, locked)

Escaped Mutant for Mutator "TrueValue": --- Original +++ New @@ @@ * * @throws Throwable */ - public final function saveOrFail(bool $cascade = true) : StateInterface + public final function saveOrFail(bool $cascade = false) : StateInterface { /** @var EntityManager $entityManager */ $entityManager = Facade::getEntityManager();
Expand All @@ -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

Check warning on line 101 in src/ActiveRecord.php

View workflow job for this annotation

GitHub Actions / mutation-testing (ubuntu-latest, 8.2, locked)

Escaped Mutant for Mutator "TrueValue": --- Original +++ New @@ @@ $entityManager->persist($this, $cascade); return $entityManager->run(); } - public final function persist(bool $cascade = true) : EntityManagerInterface + public final function persist(bool $cascade = false) : EntityManagerInterface { return Facade::getEntityManager()->persist($this, $cascade); }
{
return Facade::getEntityManager()->persist($this, $cascade);
}

/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws Throwable
*/
final public function delete(bool $cascade = true): StateInterface

Check warning on line 109 in src/ActiveRecord.php

View workflow job for this annotation

GitHub Actions / mutation-testing (ubuntu-latest, 8.2, locked)

Escaped Mutant for Mutator "TrueValue": --- Original +++ New @@ @@ /** * @throws Throwable */ - public final function delete(bool $cascade = true) : StateInterface + public final function delete(bool $cascade = false) : StateInterface { /** @var EntityManager $entityManager */ $entityManager = Facade::getEntityManager();
Expand All @@ -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
{
Expand All @@ -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

Check warning on line 133 in src/ActiveRecord.php

View workflow job for this annotation

GitHub Actions / mutation-testing (ubuntu-latest, 8.2, locked)

Escaped Mutant for Mutator "TrueValue": --- Original +++ New @@ @@ /** * Prepares the current entity for deletion. */ - public final function remove(bool $cascade = true) : EntityManagerInterface + public final function remove(bool $cascade = false) : EntityManagerInterface { /** @var EntityManager $entityManager */ $entityManager = Facade::getEntityManager();
{
Expand Down
54 changes: 37 additions & 17 deletions src/Facade.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@
use Cycle\ORM\EntityManager;
use Cycle\ORM\EntityManagerInterface;
use Cycle\ORM\ORMInterface;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use Throwable;

use function sprintf;

/**
* @internal
*/
class Facade
{
private static ?ORMInterface $orm = null;
Expand All @@ -29,27 +34,13 @@ 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);

Check warning on line 41 in src/Facade.php

View workflow job for this annotation

GitHub Actions / mutation-testing (ubuntu-latest, 8.2, locked)

Escaped Mutant for Mutator "AssignCoalesce": --- Original +++ New @@ @@ */ public static function getOrm() : ORMInterface { - return self::$orm ??= self::getFromContainer(ORMInterface::class); + return self::$orm = self::getFromContainer(ORMInterface::class); } public static function getEntityManager() : EntityManagerInterface {
}

/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public static function getEntityManager(): EntityManagerInterface
{
return self::$entityManager ??= new EntityManager(self::getOrm());
Expand All @@ -61,4 +52,33 @@ public static function reset(): void
self::$entityManager = null;
self::$container = null;
}

/**
* @template T of object
*
* @param class-string<T> $class
*
* @throws ConfigurationException
*
* @return T
*/
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()',

Check warning on line 71 in src/Facade.php

View workflow job for this annotation

GitHub Actions / mutation-testing (ubuntu-latest, 8.2, locked)

Escaped Mutant for Mutator "Concat": --- Original +++ New @@ @@ 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()')); + null === self::$container and throw new ConfigurationException(sprintf('Container has not been set. Please set the container first using %s method.', '::setContainer()' . self::class)); // Pull service from container try { return self::$container->get($class);
),
);

// 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);
}
}
}
24 changes: 0 additions & 24 deletions tests/src/ActiveRecordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -29,9 +27,6 @@ public function tearDown(): void

/**
* @test
*
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
#[Test]
public function it_finds_one_entity(): void
Expand All @@ -47,9 +42,6 @@ public function it_finds_one_entity(): void

/**
* @test
*
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
#[Test]
public function it_finds_all_entities(): void
Expand All @@ -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
Expand All @@ -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
Expand All @@ -94,8 +80,6 @@ public function it_uses_query_to_select_entity(): void
/**
* @test
*
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws Throwable
*/
#[Test]
Expand All @@ -114,8 +98,6 @@ public function it_saves_entity(): void
/**
* @test
*
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws Throwable
*/
#[Test]
Expand All @@ -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
Expand All @@ -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
Expand All @@ -180,8 +158,6 @@ public function it_deletes_entity(): void
/**
* @test
*
* @throws NotFoundExceptionInterface
* @throws ContainerExceptionInterface
* @throws Throwable
*/
#[Test]
Expand Down
44 changes: 33 additions & 11 deletions tests/src/FacadeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
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\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;

Expand Down Expand Up @@ -39,9 +39,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
Expand All @@ -55,8 +52,6 @@ public function it_fails_to_get_orm_from_facade_when_container_is_not_set(): voi
/**
* @test
*
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws Exception
*/
#[Test]
Expand All @@ -80,8 +75,6 @@ public function it_gets_orm_from_facade_when_container_has_orm(): void
/**
* @test
*
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws Exception
*/
#[Test]
Expand All @@ -99,16 +92,45 @@ 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();
}

/**
* @test
*
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @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
*
* @throws Exception
*/
#[Test]
Expand Down

0 comments on commit d8ef258

Please sign in to comment.