Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: refactor Facade, simplify exceptions range #16

Merged
merged 3 commits into from
May 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
{
/**
* 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 @@

/**
* 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 @@

/**
* 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 @@
/**
* 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 @@
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,27 +73,23 @@
/**
* 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();
{
/** @var EntityManager $entityManager */
$entityManager = Facade::getEntityManager();
$entityManager->persist($this, $cascade);

return $entityManager->run(throwException: false);

Check warning on line 84 in src/ActiveRecord.php

View workflow job for this annotation

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

Escaped Mutant for Mutator "FalseValue": --- Original +++ New @@ @@ /** @var EntityManager $entityManager */ $entityManager = Facade::getEntityManager(); $entityManager->persist($this, $cascade); - return $entityManager->run(throwException: false); + return $entityManager->run(throwException: true); } /** * Persists the current entity and throws an exception if an error occurs.
}

/**
* 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();
{
/** @var EntityManager $entityManager */
$entityManager = Facade::getEntityManager();
Expand All @@ -124,33 +98,25 @@
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();
{
/** @var EntityManager $entityManager */
$entityManager = Facade::getEntityManager();
$entityManager->delete($this, $cascade);

return $entityManager->run(throwException: false);

Check warning on line 115 in src/ActiveRecord.php

View workflow job for this annotation

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

Escaped Mutant for Mutator "FalseValue": --- Original +++ New @@ @@ /** @var EntityManager $entityManager */ $entityManager = Facade::getEntityManager(); $entityManager->delete($this, $cascade); - return $entityManager->run(throwException: false); + return $entityManager->run(throwException: true); } /** * @throws Throwable
}

/**
* @throws ContainerExceptionInterface
* @throws Throwable
* @throws NotFoundExceptionInterface
*/
final public function deleteOrFail(bool $cascade = true): StateInterface
{
Expand All @@ -163,11 +129,8 @@

/**
* 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();
{
/** @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 @@
}

/**
* @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 @@
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
Loading