From d3019da6d12595feee964287126883d8475f21f0 Mon Sep 17 00:00:00 2001 From: Agung Sugiarto Date: Sat, 19 Sep 2020 17:15:48 +0700 Subject: [PATCH] Refactor pass to argument and added more testing --- README.md | 2 +- src/Contracts/CriterionInterface.php | 4 +- src/Contracts/RepositoryInterface.php | 4 +- src/Contracts/ScopesInterface.php | 4 +- src/Criteria/FindWhere.php | 3 +- src/Eloquent/RepositoryAbstract.php | 3 +- src/Scopes/Scopes.php | 5 +- src/Scopes/ScopesAbstract.php | 14 ++- tests/Criteria/SampleCriteria.php | 41 +++++++ tests/Models/NewsModel.php | 2 + tests/NewsRepositoryRequestTest.php | 133 +++++++++++++++++++++++ tests/NewsRepositoryTest.php | 14 +++ tests/Repository/NewsRepositoryScope.php | 30 +++++ tests/Scopes/Clauses/MyScope.php | 16 +++ tests/Scopes/NewsScope.php | 13 +++ 15 files changed, 273 insertions(+), 15 deletions(-) create mode 100644 tests/Criteria/SampleCriteria.php create mode 100644 tests/NewsRepositoryRequestTest.php create mode 100644 tests/Repository/NewsRepositoryScope.php create mode 100644 tests/Scopes/Clauses/MyScope.php create mode 100644 tests/Scopes/NewsScope.php diff --git a/README.md b/README.md index 3f3cf7d..7cf2892 100644 --- a/README.md +++ b/README.md @@ -372,7 +372,7 @@ https://example.com/news?orderBy=email_desc&begin=2019-01-24&end=2019-01-26 You can also build your own custom scopes. In your repository override `scope()` method: ```php -public function scope($request) +public function scope(IncomingRequest $request) { // apply build-in scopes parent::scope($request); diff --git a/src/Contracts/CriterionInterface.php b/src/Contracts/CriterionInterface.php index 9bf9015..b3b69c0 100644 --- a/src/Contracts/CriterionInterface.php +++ b/src/Contracts/CriterionInterface.php @@ -2,6 +2,8 @@ namespace Fluent\Repository\Contracts; +use CodeIgniter\Model; + interface CriterionInterface { /** @@ -10,5 +12,5 @@ interface CriterionInterface * @param \CodeIgniter\Model $entity * @return mixed */ - public function apply($entity); + public function apply(Model $entity); } diff --git a/src/Contracts/RepositoryInterface.php b/src/Contracts/RepositoryInterface.php index c400847..b2d5a62 100644 --- a/src/Contracts/RepositoryInterface.php +++ b/src/Contracts/RepositoryInterface.php @@ -16,7 +16,7 @@ public function get(array $columns = ['*']); * Execute the query and get the first result. * * @param array $columns - * @return array + * @return array|object */ public function first($columns = ['*']); @@ -91,7 +91,7 @@ public function updateBatch(array $attributes, $id); /** * Delete a record by id. * - * @param int $id + * @param mixed $id * @return mixed */ public function destroy($id); diff --git a/src/Contracts/ScopesInterface.php b/src/Contracts/ScopesInterface.php index 275f722..1aca268 100644 --- a/src/Contracts/ScopesInterface.php +++ b/src/Contracts/ScopesInterface.php @@ -2,6 +2,8 @@ namespace Fluent\Repository\Contracts; +use CodeIgniter\HTTP\IncomingRequest; + interface ScopesInterface { /** @@ -10,5 +12,5 @@ interface ScopesInterface * @param \CodeIgniter\HTTP\IncomingRequest $request * @return $this */ - public function scope($request); + public function scope(IncomingRequest $request); } diff --git a/src/Criteria/FindWhere.php b/src/Criteria/FindWhere.php index 7a596a8..051fac9 100644 --- a/src/Criteria/FindWhere.php +++ b/src/Criteria/FindWhere.php @@ -2,6 +2,7 @@ namespace Fluent\Repository\Criteria; +use CodeIgniter\Model; use Fluent\Repository\Contracts\CriterionInterface; class FindWhere implements CriterionInterface @@ -23,7 +24,7 @@ public function __construct(array $conditions) /** * @inheritdoc */ - public function apply($entity) + public function apply(Model $entity) { foreach ($this->conditions as $field => $value) { if (is_array($value)) { diff --git a/src/Eloquent/RepositoryAbstract.php b/src/Eloquent/RepositoryAbstract.php index 274e68b..05cefad 100644 --- a/src/Eloquent/RepositoryAbstract.php +++ b/src/Eloquent/RepositoryAbstract.php @@ -2,6 +2,7 @@ namespace Fluent\Repository\Eloquent; +use CodeIgniter\HTTP\IncomingRequest; use Fluent\Repository\Scopes\Scopes; use Fluent\Repository\Contracts\ScopesInterface; use Fluent\Repository\Contracts\CriteriaInterface; @@ -45,7 +46,7 @@ public function withCriteria(array $criteria) /** * @inheritdoc */ - public function scope($request) + public function scope(IncomingRequest $request) { $this->entity = (new Scopes($request, $this->searchable))->scope($this->entity); diff --git a/src/Scopes/Scopes.php b/src/Scopes/Scopes.php index cf9a4eb..ba8d8ac 100644 --- a/src/Scopes/Scopes.php +++ b/src/Scopes/Scopes.php @@ -2,6 +2,7 @@ namespace Fluent\Repository\Scopes; +use CodeIgniter\HTTP\IncomingRequest; use Fluent\Repository\Scopes\Clauses\WhereScope; use Fluent\Repository\Scopes\Clauses\OrderByScope; use Fluent\Repository\Scopes\Clauses\OrWhereScope; @@ -26,7 +27,7 @@ class Scopes extends ScopesAbstract * @param array $searchable * @return void */ - public function __construct($request, $searchable) + public function __construct(IncomingRequest $request, $searchable) { parent::__construct($request); @@ -45,7 +46,7 @@ public function __construct($request, $searchable) * @param string $key * @return string */ - protected function mappings($key) + protected function mappings(string $key) { $mappings = [ 'or' => OrWhereScope::class, diff --git a/src/Scopes/ScopesAbstract.php b/src/Scopes/ScopesAbstract.php index bffbdc0..3fdd7d3 100644 --- a/src/Scopes/ScopesAbstract.php +++ b/src/Scopes/ScopesAbstract.php @@ -2,9 +2,11 @@ namespace Fluent\Repository\Scopes; +use CodeIgniter\HTTP\IncomingRequest; + class ScopesAbstract { - /** @var \CodeIgniter\HTTP\IncomingRequest $request */ + /** @var \CodeIgniter\HTTP\IncomingRequest */ protected $request; /** @var array $scopes */ @@ -15,7 +17,7 @@ class ScopesAbstract * * @param \CodeIgniter\HTTP\IncomingRequest $request */ - public function __construct($request) + public function __construct(IncomingRequest $request) { $this->request = $request; } @@ -23,7 +25,7 @@ public function __construct($request) /** * In your repository define which fields can be used to scope your queries. * - * @param \CodeIgniter\Database\BaseBuilder $builder + * @param \CodeIgniter\Database\BaseBuilder|\CodeIgniter\Model $builder * @return \CodeIgniter\Database\BaseBuilder $builder */ public function scope($builder) @@ -43,7 +45,7 @@ public function scope($builder) * @param string $scope * @return object */ - protected function resolveScope($scope) + protected function resolveScope(string $scope) { return new $this->scopes[$scope](); } @@ -56,7 +58,7 @@ protected function resolveScope($scope) protected function getScopes() { return $this->filterScopes( - $this->request->getVar(array_keys($this->scopes)) + $this->request->getGet(array_keys($this->scopes)) ); } @@ -66,7 +68,7 @@ protected function getScopes() * @param array $scopes * @return array */ - protected function filterScopes($scopes) + protected function filterScopes(array $scopes) { return array_filter($scopes, function ($scope) { return isset($scope); diff --git a/tests/Criteria/SampleCriteria.php b/tests/Criteria/SampleCriteria.php new file mode 100644 index 0000000..4ae4748 --- /dev/null +++ b/tests/Criteria/SampleCriteria.php @@ -0,0 +1,41 @@ +conditions = $conditions; + } + + /** + * @inheritdoc + */ + public function apply(Model $entity) + { + foreach ($this->conditions as $field => $value) + { + if (is_array($value)) { + list($field, $condition, $val) = $value; + $entity = $entity->orWhere($field . $condition, $val); + } else { + $entity = $entity->where($field, $value); + } + + return $entity; + } + } +} \ No newline at end of file diff --git a/tests/Models/NewsModel.php b/tests/Models/NewsModel.php index e0149bc..2570650 100644 --- a/tests/Models/NewsModel.php +++ b/tests/Models/NewsModel.php @@ -11,6 +11,8 @@ class NewsModel extends Model protected $allowedFields = ['title', 'description']; protected $useTimestamps = true; + public $orderable = ['title']; + /** * Faker generator. * diff --git a/tests/NewsRepositoryRequestTest.php b/tests/NewsRepositoryRequestTest.php new file mode 100644 index 0000000..f47e3b8 --- /dev/null +++ b/tests/NewsRepositoryRequestTest.php @@ -0,0 +1,133 @@ +repository = new NewsRepositoryScope(); + + $this->request = Services::request(); + } + + public function testRepositoryMyCustomScope() + { + $this->request->setMethod('get') + ->setGlobal('get', [ + 'id' => '1', + ] + ); + + $this->assertNotEmpty($this->repository->scope(Services::request())->first()); + } + + public function testRepositoryMyCustomScopeIsNull() + { + $this->request->setMethod('get') + ->setGlobal('get', [ + 'id' => '1000', + ] + ); + + $this->assertNull($this->repository->scope(Services::request())->first()); + } + + public function testRepositoryScopeTitle() + { + $this->request->setMethod('get') + ->setGlobal('get', [ + 'title' => 'A', + ] + ); + + $this->assertNotEmpty($this->repository->scope(Services::request())->first()); + } + + public function testRepositoryScopeTitleIsNull() + { + $this->request->setMethod('get') + ->setGlobal('get', [ + 'title' => 'Aaaaaa', + ] + ); + + $this->assertNull($this->repository->scope(Services::request())->first()); + } + + public function testRepositoryScopeDescription() + { + $this->request->setMethod('get') + ->setGlobal('get', [ + 'description' => 'A', + ] + ); + + $this->assertNotEmpty($this->repository->scope(Services::request())->first()); + } + + public function testRepositoryScopeDescriptionIsNull() + { + $this->request->setMethod('get') + ->setGlobal('get', [ + 'description' => 'Aaaaaa', + ] + ); + + $this->assertNull($this->repository->scope(Services::request())->first()); + } + + public function testRepositoryScopeRequestOrderByAsc() + { + $this->request->setMethod('get') + ->setGlobal('get', [ + 'orderBy' => 'title_asc', + ] + ); + + $this->assertNotEmpty($this->repository->scope(Services::request())->paginate()); + } + + public function testRepositoryScopeRequestOrderByDesc() + { + $this->request->setMethod('get') + ->setGlobal('get', [ + 'orderBy' => 'title_desc', + ] + ); + + $this->assertNotEmpty($this->repository->scope(Services::request())->paginate()); + } + + public function testRepositoryScopeRequestBeginEnd() + { + $this->request->setMethod('get') + ->setGlobal('get', [ + 'begin' => Time::now(), + 'end' => Time::now(), + ] + ); + + $this->assertNotNull($this->repository->scope(Services::request())->paginate()); + } +} \ No newline at end of file diff --git a/tests/NewsRepositoryTest.php b/tests/NewsRepositoryTest.php index f942d4a..3a18db0 100644 --- a/tests/NewsRepositoryTest.php +++ b/tests/NewsRepositoryTest.php @@ -3,6 +3,7 @@ namespace Fluent\Repository\Tests; use CodeIgniter\Test\CIDatabaseTestCase; +use Fluent\Repository\Tests\Criteria\SampleCriteria; use Fluent\Repository\Tests\Repository\NewsRepository; use Tests\Support\Database\Seeds\NewsSeeder; @@ -44,6 +45,19 @@ public function testRepositoryFindWhere() ); } + public function testRepositoryWithCriteria() + { + $this->assertNotEmpty( + $this->repository->withCriteria([ + new SampleCriteria([ + 'id' => 1, + ['id', '=', 2] + ]), + ]) + ->get() + ); + } + public function testRepositoryPaginate() { $this->assertNotEmpty($this->repository->paginate()); diff --git a/tests/Repository/NewsRepositoryScope.php b/tests/Repository/NewsRepositoryScope.php new file mode 100644 index 0000000..17b1b4e --- /dev/null +++ b/tests/Repository/NewsRepositoryScope.php @@ -0,0 +1,30 @@ + 'like', + 'description' => 'orLike', + ]; + + public function scope(IncomingRequest $request) + { + parent::scope($request); + + $this->entity = (new NewsScope($request))->scope($this->entity); + + return $this->entity; + } + + public function entity() + { + return NewsModel::class; + } +} \ No newline at end of file diff --git a/tests/Scopes/Clauses/MyScope.php b/tests/Scopes/Clauses/MyScope.php new file mode 100644 index 0000000..982afbe --- /dev/null +++ b/tests/Scopes/Clauses/MyScope.php @@ -0,0 +1,16 @@ +where($scope, $value); + } +} \ No newline at end of file diff --git a/tests/Scopes/NewsScope.php b/tests/Scopes/NewsScope.php new file mode 100644 index 0000000..1d703ff --- /dev/null +++ b/tests/Scopes/NewsScope.php @@ -0,0 +1,13 @@ + MyScope::class + ]; +} \ No newline at end of file