diff --git a/readme.md b/readme.md index 588e920..0638303 100644 --- a/readme.md +++ b/readme.md @@ -46,8 +46,7 @@ OldPeopleFilter.php declare(strict_types=1); -use Illuminate\Database\Query\Builder; -use DevMakerLab\LaravelFilters\AbstractFilter; +use ... class OldPeopleFilter extends AbstractFilter { @@ -66,27 +65,17 @@ PeopleRepository.php declare(strict_types=1); -use DevMakerLab\LaravelFilters\AbstractFilterableRepository; +use ... -class PeopleRepository extends AbstractFilterableRepository +class PeopleRepository extends AbstractFilterableRepository { - private DatabaseManager $databaseManager; + protected string $table = 'people'; + protected array $attributes = ['firstname', 'lastname', 'age', 'gender']; + protected bool $shouldTransform = true; public function __construct(DatabaseManager $databaseManager) { - $this->databaseManager = $databaseManager; - } - - public function get(array $args): array - { - $queryBuilder = $this->databaseManager->table('people') - ->select(['firstname', 'lastname', 'age', 'gender']); - - $this->applyFilters($queryBuilder, $args); - - $people = $queryBuilder->get(); - - return $this->transform($people); + parent::__construct($databaseManager); } public function transform(Collection $people): array diff --git a/src/AbstractFilterableRepository.php b/src/AbstractFilterableRepository.php index e9cc44e..987d7fd 100644 --- a/src/AbstractFilterableRepository.php +++ b/src/AbstractFilterableRepository.php @@ -5,12 +5,21 @@ namespace DevMakerLab\LaravelFilters; use Illuminate\Database\Query\Builder; +use Illuminate\Database\DatabaseManager; abstract class AbstractFilterableRepository { + protected string $table; + protected array $attributes = []; + protected ?int $limit = null; protected array $filters = []; - protected ?int $limit = null; + protected DatabaseManager $databaseManager; + + public function __construct(DatabaseManager $databaseManager) + { + $this->databaseManager = $databaseManager; + } /** * @throws FilterClassNotFound @@ -52,6 +61,26 @@ public function resetLimit(): self return $this; } + public function get(array $args = []): iterable + { + $queryBuilder = $this->databaseManager->table($this->table) + ->select($this->attributes); + + $this->applyFilters($queryBuilder, $args); + + $result = $queryBuilder->get(); + + if (property_exists($this, 'shouldTransform') && $this->shouldTransform === true) { + if (method_exists($this, 'transform')) { + return $this->transform($result); + } else { + throw new TransformMethodNotImplementedException(static::class); + } + } + + return $result; + } + public function applyFilters(Builder &$builder, array $args): self { foreach ($this->filters as $filter) { diff --git a/src/TransformMethodNotImplementedException.php b/src/TransformMethodNotImplementedException.php new file mode 100644 index 0000000..9f644d0 --- /dev/null +++ b/src/TransformMethodNotImplementedException.php @@ -0,0 +1,15 @@ +databaseManager = $databaseManager; + parent::__construct($databaseManager); } - public function get(array $args): PeopleEntityList - { - $queryBuilder = $this->databaseManager->table('people') - ->select(['firstname', 'lastname', 'age', 'gender']); - - $this->applyFilters($queryBuilder, $args); - - $people = $queryBuilder->get(); - - return $this->transform($people); - } - - public function transform(\Illuminate\Support\Collection $people): PeopleEntityList + public function transform(Collection $people): PeopleEntityList { $people->transform(function ($person) { return new PeopleEntity([ diff --git a/tests/Feature/PeopleRepositoryTest.php b/tests/Feature/PeopleRepositoryTest.php index 70d6423..cf8f4e1 100644 --- a/tests/Feature/PeopleRepositoryTest.php +++ b/tests/Feature/PeopleRepositoryTest.php @@ -2,6 +2,8 @@ declare(strict_types=1); +namespace Tests\Feature; + use Tests\TestCase; use Tests\Example\Filters\OldPeopleFilter; use Tests\Example\Entities\PeopleEntityList; diff --git a/tests/TestCase.php b/tests/TestCase.php index c408372..ed1d90a 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -4,9 +4,13 @@ namespace Tests; +use Illuminate\Support\Collection; use Tests\Example\PeopleRepository; use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Query\Builder; +use Illuminate\Database\DatabaseManager; use Illuminate\Database\Schema\Blueprint; +use DevMakerLab\LaravelFilters\AbstractFilterableRepository; class TestCase extends \Orchestra\Testbench\TestCase { @@ -36,4 +40,42 @@ public function createPeople(array $peoples): void ->table('people') ->insert($peoples); } + + public function getAbstractRepository(bool $shouldTransform = true): AbstractFilterableRepository + { + $db = $this->partialMock(DatabaseManager::class); + $queryBuilder = $this->partialMock(Builder::class); + $db->shouldReceive('table') + ->andReturn($queryBuilder); + $db->shouldReceive('select') + ->andReturn($queryBuilder); + + $queryBuilder->shouldReceive('get') + ->andReturn(new Collection([ + 0 => 'first item', + 1 => 'second item', + ])); + + return new class($db, $shouldTransform) extends AbstractFilterableRepository { + protected string $table = 'table'; + protected array $attributes = []; + protected bool $shouldTransform; + + public function __construct(DatabaseManager $databaseManager, bool $shouldTransform) + { + parent::__construct($databaseManager); + $this->shouldTransform = $shouldTransform; + } + + public function getFilters(): array + { + return $this->filters; + } + + public function getLimit(): ?int + { + return $this->limit; + } + }; + } } diff --git a/tests/Unit/AbstractFilterableRepositoryTest.php b/tests/Unit/AbstractFilterableRepositoryTest.php index 32ec8a1..261fdba 100644 --- a/tests/Unit/AbstractFilterableRepositoryTest.php +++ b/tests/Unit/AbstractFilterableRepositoryTest.php @@ -2,18 +2,41 @@ declare(strict_types=1); +namespace Tests\Unit; + use Tests\TestCase; +use Illuminate\Support\Collection; use DevMakerLab\LaravelFilters\AbstractFilter; use DevMakerLab\LaravelFilters\FilterClassNotFound; use DevMakerLab\LaravelFilters\IncorrectFilterException; -use DevMakerLab\LaravelFilters\AbstractFilterableRepository; +use DevMakerLab\LaravelFilters\TransformMethodNotImplementedException; class AbstractFilterableRepositoryTest extends TestCase { + public function testExceptionThrownWhenAskedForTransformWithoutDefiningTransformMethod(): void + { + $abstractRepository = $this->getAbstractRepository(); + + $this->expectException(TransformMethodNotImplementedException::class); + $abstractRepository->get(); + } + + public function testCanGet(): void + { + $abstractRepository = $this->getAbstractRepository(false); + + $result = $abstractRepository->get(); + $this->assertInstanceOf(Collection::class, $result); + $this->assertCount(2, $result); + $this->assertSame([ + 'first item', + 'second item', + ], $result->toArray()); + } + public function testExceptionThrownWhenAddingNonExistingFilter(): void { - $abstractRepository = new class extends AbstractFilterableRepository { - }; + $abstractRepository = $this->getAbstractRepository(); $this->expectException(FilterClassNotFound::class); $abstractRepository->addFilter(FooFilter::class); @@ -21,46 +44,36 @@ public function testExceptionThrownWhenAddingNonExistingFilter(): void public function testExceptionThrownWhenAddingFilterWhichIsNotExtendingAbstractFilter(): void { - $abstractRepository = new class extends AbstractFilterableRepository { - }; + $abstractRepository = $this->getAbstractRepository(); + $filter = new class { }; $this->expectException(IncorrectFilterException::class); - $abstractRepository->addFilter(get_class($filter)); + $abstractRepository->addFilter(\get_class($filter)); } public function testCanAddFilter(): void { - $abstractRepository = new class extends AbstractFilterableRepository { - public function getFilters(): array - { - return $this->filters; - } - }; + $abstractRepository = $this->getAbstractRepository(); $filter = new class extends AbstractFilter { }; - $abstractRepository->addFilter(get_class($filter)); + $abstractRepository->addFilter(\get_class($filter)); $this->assertCount(1, $abstractRepository->getFilters()); - $this->assertSame(get_class($filter), $abstractRepository->getFilters()[0]); + $this->assertSame(\get_class($filter), $abstractRepository->getFilters()[0]); } public function testCanResetFilters(): void { - $abstractRepository = new class extends AbstractFilterableRepository { - public function getFilters(): array - { - return $this->filters; - } - }; + $abstractRepository = $this->getAbstractRepository(); $filter = new class extends AbstractFilter { }; - $abstractRepository->addFilter(get_class($filter)); + $abstractRepository->addFilter(\get_class($filter)); $this->assertCount(1, $abstractRepository->getFilters()); $abstractRepository->resetFilters(); @@ -69,12 +82,7 @@ public function getFilters(): array public function testCanSpecifyLimit(): void { - $abstractRepository = new class extends AbstractFilterableRepository { - public function getLimit(): ?int - { - return $this->limit; - } - }; + $abstractRepository = $this->getAbstractRepository(); $this->assertNull($abstractRepository->getLimit()); @@ -84,12 +92,7 @@ public function getLimit(): ?int public function testCanResetLimit(): void { - $abstractRepository = new class extends AbstractFilterableRepository { - public function getLimit(): ?int - { - return $this->limit; - } - }; + $abstractRepository = $this->getAbstractRepository(); $this->assertNull($abstractRepository->getLimit());