From 13a5f5fe42a16186ed58fc77f651f45b7b606514 Mon Sep 17 00:00:00 2001 From: Eduard Lupacescu Date: Mon, 11 May 2020 14:31:09 +0300 Subject: [PATCH 1/4] filters --- routes/api.php | 5 + src/BooleanFilter.php | 20 ++++ src/Filter.php | 86 +++++++++++++++++ .../RepositoryFilterController.php | 15 +++ .../Requests/RepositoryFiltersRequest.php | 7 ++ src/Repositories/Repository.php | 22 ++++- src/SelectFilter.php | 9 ++ .../Search/RepositorySearchService.php | 43 ++++++++- src/TimestampFilter.php | 16 ++++ .../RepositoryFilterControllerTest.php | 92 +++++++++++++++++++ tests/Fixtures/Post/ActiveBooleanFilter.php | 22 +++++ .../Fixtures/Post/CreatedAfterDateFilter.php | 14 +++ tests/Fixtures/Post/Post.php | 2 + tests/Fixtures/Post/PostRepository.php | 9 ++ tests/Fixtures/Post/SelectCategoryFilter.php | 25 +++++ .../2019_12_22_000005_create_posts_table.php | 2 + 16 files changed, 384 insertions(+), 5 deletions(-) create mode 100644 src/BooleanFilter.php create mode 100644 src/Filter.php create mode 100644 src/Http/Controllers/RepositoryFilterController.php create mode 100644 src/Http/Requests/RepositoryFiltersRequest.php create mode 100644 src/SelectFilter.php create mode 100644 src/TimestampFilter.php create mode 100644 tests/Controllers/RepositoryFilterControllerTest.php create mode 100644 tests/Fixtures/Post/ActiveBooleanFilter.php create mode 100644 tests/Fixtures/Post/CreatedAfterDateFilter.php create mode 100644 tests/Fixtures/Post/SelectCategoryFilter.php diff --git a/routes/api.php b/routes/api.php index 1d93040ff..b44788a43 100644 --- a/routes/api.php +++ b/routes/api.php @@ -2,6 +2,7 @@ use Binaryk\LaravelRestify\Http\Controllers\GlobalSearchController; use Binaryk\LaravelRestify\Http\Controllers\RepositoryDestroyController; +use Binaryk\LaravelRestify\Http\Controllers\RepositoryFilterController; use Binaryk\LaravelRestify\Http\Controllers\RepositoryIndexController; use Binaryk\LaravelRestify\Http\Controllers\RepositoryShowController; use Binaryk\LaravelRestify\Http\Controllers\RepositoryStoreController; @@ -11,6 +12,9 @@ // Global Search... Route::get('/search', '\\'.GlobalSearchController::class); +// Filters +Route::get('/{repository}/filters', '\\' . RepositoryFilterController::class); + // API CRUD Route::get('/{repository}', '\\'.RepositoryIndexController::class); Route::post('/{repository}', '\\'.RepositoryStoreController::class); @@ -18,3 +22,4 @@ Route::patch('/{repository}/{repositoryId}', '\\'.RepositoryUpdateController::class); Route::put('/{repository}/{repositoryId}', '\\'.RepositoryUpdateController::class); Route::delete('/{repository}/{repositoryId}', '\\'.RepositoryDestroyController::class); + diff --git a/src/BooleanFilter.php b/src/BooleanFilter.php new file mode 100644 index 000000000..1b4015bdf --- /dev/null +++ b/src/BooleanFilter.php @@ -0,0 +1,20 @@ +options($request))->mapWithKeys(function ($key) use ($filter) { + return [$key => data_get($filter, $key)]; + })->toArray(); + + $this->value = $keyValues; + } +} diff --git a/src/Filter.php b/src/Filter.php new file mode 100644 index 000000000..927a6b8f3 --- /dev/null +++ b/src/Filter.php @@ -0,0 +1,86 @@ +booted(); + } + + protected function booted() + { + // + } + + abstract public function filter(RestifyRequest $request, $query, $value); + + public function canSee(Closure $callback) + { + $this->canSeeCallback = $callback; + + return $this; + } + + public function authorizedToSee(RestifyRequest $request) + { + return $this->canSeeCallback ? call_user_func($this->canSeeCallback, $request) : true; + } + + public function key() + { + return static::class; + } + + protected function getType() + { + return $this->type; + } + + public function options(Request $request) + { + // noop + } + + public function invalidPayloadValue(Request $request, $value) + { + if (is_array($value)) { + return count($value) < 1; + } elseif (is_string($value)) { + return trim($value) === ''; + } + + return is_null($value); + } + + public function resolve(RestifyRequest $request, $filter) + { + $this->value = $filter['value']; + } + + public function jsonSerialize() + { + return [ + 'class' => static::class, + 'type' => $this->getType(), + 'options' => collect($this->options(app(Request::class)))->map(function ($value, $key) { + return is_array($value) ? ($value + ['property' => $key]) : ['label' => $key, 'property' => $value]; + })->values()->all(), + ]; + } +} diff --git a/src/Http/Controllers/RepositoryFilterController.php b/src/Http/Controllers/RepositoryFilterController.php new file mode 100644 index 000000000..cdd416e8f --- /dev/null +++ b/src/Http/Controllers/RepositoryFilterController.php @@ -0,0 +1,15 @@ +repository(); + + return $this->response()->data($repository->availableFilters($request)); + } +} diff --git a/src/Http/Requests/RepositoryFiltersRequest.php b/src/Http/Requests/RepositoryFiltersRequest.php new file mode 100644 index 000000000..9e07896f2 --- /dev/null +++ b/src/Http/Requests/RepositoryFiltersRequest.php @@ -0,0 +1,7 @@ +getKey(); } + + public function availableFilters(RestifyRequest $request) + { + return collect($this->filter($this->filters($request)))->each(fn(Filter $filter) => $filter->authorizedToSee($request)) + ->values(); + } } diff --git a/src/SelectFilter.php b/src/SelectFilter.php new file mode 100644 index 000000000..6c99102ac --- /dev/null +++ b/src/SelectFilter.php @@ -0,0 +1,9 @@ +prepareMatchFields($request, $this->prepareSearchFields($request, $repository::query(), $this->fixedInput), $this->fixedInput); + $query = $this->applyFilters($request, $repository, $query); + return tap($this->prepareRelations($request, $this->prepareOrders($request, $query), $this->fixedInput), $this->applyIndexQuery($request, $repository)); } @@ -24,7 +27,7 @@ public function prepareMatchFields(RestifyRequest $request, $query, $extra = []) { $model = $query->getModel(); foreach ($this->repository->getMatchByFields() as $key => $type) { - if (! $request->has($key) && ! data_get($extra, "match.$key")) { + if (!$request->has($key) && !data_get($extra, "match.$key")) { continue; } @@ -57,7 +60,7 @@ public function prepareMatchFields(RestifyRequest $request, $query, $extra = []) case RestifySearchable::MATCH_INTEGER: case 'number': case 'int': - $query->where($field, '=', (int) $match); + $query->where($field, '=', (int)$match); break; } } @@ -122,7 +125,7 @@ public function prepareSearchFields(RestifyRequest $request, $query, $extra = [] $likeOperator = $connectionType == 'pgsql' ? 'ilike' : 'like'; foreach ($this->repository->getSearchableFields() as $column) { - $query->orWhere($model->qualifyColumn($column), $likeOperator, '%'.$search.'%'); + $query->orWhere($model->qualifyColumn($column), $likeOperator, '%' . $search . '%'); } }); @@ -173,6 +176,38 @@ public function setOrder($query, $param) protected function applyIndexQuery(RestifyRequest $request, Repository $repository) { - return fn ($query) => $repository::indexQuery($request, $query); + return fn($query) => $repository::indexQuery($request, $query); + } + + protected function applyFilters(RestifyRequest $request, Repository $repository, $query) + { + if (!empty($request->filters)) { + $filters = json_decode(base64_decode($request->filters), true); + + collect($filters) + ->map(function ($filter) use ($request, $repository) { + /** * @var Filter $matchingFilter */ + $matchingFilter = $repository->availableFilters($request)->first(function ($availableFilter) use ($filter) { + return $filter['class'] === $availableFilter->key(); + }); + + + if (is_null($matchingFilter)) { + return false; + } + + if ($matchingFilter->invalidPayloadValue($request, $filter['value'])) { + return false; + }; + + $matchingFilter->resolve($request, $filter['value']); + + return $matchingFilter; + }) + ->filter() + ->each(fn(Filter $filter) => $filter->filter($request, $query, $filter->value)); + } + + return $query; } } diff --git a/src/TimestampFilter.php b/src/TimestampFilter.php new file mode 100644 index 000000000..c1f209dab --- /dev/null +++ b/src/TimestampFilter.php @@ -0,0 +1,16 @@ +value = Carbon::parse($value); + } +} diff --git a/tests/Controllers/RepositoryFilterControllerTest.php b/tests/Controllers/RepositoryFilterControllerTest.php new file mode 100644 index 000000000..1e5ff5901 --- /dev/null +++ b/tests/Controllers/RepositoryFilterControllerTest.php @@ -0,0 +1,92 @@ +withoutExceptionHandling() + ->getJson('restify-api/posts/filters') + ->dump() + ->assertStatus(200); + + $this->assertCount(3, $response->json('data')); + } + + public function test_the_boolean_filter_is_applied() + { + factory(Post::class)->create(['is_active' => false,]); + factory(Post::class)->create(['is_active' => true,]); + + $filters = base64_encode(json_encode([ + [ + 'class' => ActiveBooleanFilter::class, + 'value' => [ + 'is_active' => false, + ], + ] + ])); + + $response = $this + ->withoutExceptionHandling() + ->getJson('restify-api/posts?filters=' . $filters) + ->dump() + ->assertStatus(200); + + $this->assertCount(1, $response->json('data')); + } + + public function test_the_select_filter_is_applied() + { + factory(Post::class)->create(['category' => 'movie',]); + factory(Post::class)->create(['category' => 'article',]); + + $filters = base64_encode(json_encode([ + [ + 'class' => SelectCategoryFilter::class, + 'value' => 'article' + ] + ])); + + $response = $this + ->withExceptionHandling() + ->getJson('restify-api/posts?filters=' . $filters) + ->assertStatus(200); + + $this->assertCount(1, $response->json('data')); + } + + public function test_the_timestamp_filter_is_applied() + { + factory(Post::class)->create(['created_at' => now()->addYear(),]); + factory(Post::class)->create(['created_at' => now()->subYear(),]); + + $filters = base64_encode(json_encode([ + [ + 'class' => UserRepository::class, + 'value' => now()->addWeek()->timestamp, + ], + [ + 'class' => CreatedAfterDateFilter::class, + 'value' => now()->addWeek()->timestamp, + ] + ])); + + $response = $this + ->withExceptionHandling() + ->getJson('restify-api/posts?filters=' . $filters) + ->dump() + ->assertStatus(200); + + $this->assertCount(1, $response->json('data')); + } +} diff --git a/tests/Fixtures/Post/ActiveBooleanFilter.php b/tests/Fixtures/Post/ActiveBooleanFilter.php new file mode 100644 index 000000000..6fdae34e5 --- /dev/null +++ b/tests/Fixtures/Post/ActiveBooleanFilter.php @@ -0,0 +1,22 @@ +where('is_active', $value['is_active']); + } + + public function options(Request $request) + { + return [ + 'Is Active' => 'is_active', + ]; + } +} diff --git a/tests/Fixtures/Post/CreatedAfterDateFilter.php b/tests/Fixtures/Post/CreatedAfterDateFilter.php new file mode 100644 index 000000000..36645d728 --- /dev/null +++ b/tests/Fixtures/Post/CreatedAfterDateFilter.php @@ -0,0 +1,14 @@ +whereDate('created_at', '>', $value); + } +} diff --git a/tests/Fixtures/Post/Post.php b/tests/Fixtures/Post/Post.php index ffb7ce6c1..ba578b9f1 100644 --- a/tests/Fixtures/Post/Post.php +++ b/tests/Fixtures/Post/Post.php @@ -20,6 +20,8 @@ class Post extends Model implements RestifySearchable 'image', 'title', 'description', + 'category', + 'is_active', ]; public function user() diff --git a/tests/Fixtures/Post/PostRepository.php b/tests/Fixtures/Post/PostRepository.php index 6f34543aa..5dd52427a 100644 --- a/tests/Fixtures/Post/PostRepository.php +++ b/tests/Fixtures/Post/PostRepository.php @@ -49,4 +49,13 @@ public function fieldsForStore(RestifyRequest $request) ]), ]; } + + public function filters(RestifyRequest $request) + { + return [ + ActiveBooleanFilter::new()->canSee(fn() => true), + SelectCategoryFilter::new(), + CreatedAfterDateFilter::new(), + ]; + } } diff --git a/tests/Fixtures/Post/SelectCategoryFilter.php b/tests/Fixtures/Post/SelectCategoryFilter.php new file mode 100644 index 000000000..625cffd59 --- /dev/null +++ b/tests/Fixtures/Post/SelectCategoryFilter.php @@ -0,0 +1,25 @@ +where('category', $value); + } + + public function options(Request $request) + { + return [ + 'Movie category' => 'movie', + + 'Article Category' => 'article', + ]; + } +} diff --git a/tests/Migrations/2019_12_22_000005_create_posts_table.php b/tests/Migrations/2019_12_22_000005_create_posts_table.php index b1fa91dbb..c49b70c58 100644 --- a/tests/Migrations/2019_12_22_000005_create_posts_table.php +++ b/tests/Migrations/2019_12_22_000005_create_posts_table.php @@ -19,6 +19,8 @@ public function up() $table->string('title'); $table->longText('description')->nullable(); $table->string('image')->nullable(); + $table->string('category')->nullable(); + $table->boolean('is_active')->default(true); $table->timestamps(); }); } From 50c7a6339c48ddfb2a923772c03c2ee5802d29f9 Mon Sep 17 00:00:00 2001 From: Lupacescu Eduard Date: Mon, 11 May 2020 14:31:32 +0300 Subject: [PATCH 2/4] Apply fixes from StyleCI (#175) --- routes/api.php | 3 +-- src/BooleanFilter.php | 1 - src/Repositories/Repository.php | 4 +-- src/SelectFilter.php | 1 - .../Search/RepositorySearchService.php | 17 ++++++------ .../RepositoryFilterControllerTest.php | 26 +++++++++---------- tests/Fixtures/Post/PostRepository.php | 2 +- 7 files changed, 24 insertions(+), 30 deletions(-) diff --git a/routes/api.php b/routes/api.php index b44788a43..dec06ba36 100644 --- a/routes/api.php +++ b/routes/api.php @@ -13,7 +13,7 @@ Route::get('/search', '\\'.GlobalSearchController::class); // Filters -Route::get('/{repository}/filters', '\\' . RepositoryFilterController::class); +Route::get('/{repository}/filters', '\\'.RepositoryFilterController::class); // API CRUD Route::get('/{repository}', '\\'.RepositoryIndexController::class); @@ -22,4 +22,3 @@ Route::patch('/{repository}/{repositoryId}', '\\'.RepositoryUpdateController::class); Route::put('/{repository}/{repositoryId}', '\\'.RepositoryUpdateController::class); Route::delete('/{repository}/{repositoryId}', '\\'.RepositoryDestroyController::class); - diff --git a/src/BooleanFilter.php b/src/BooleanFilter.php index 1b4015bdf..df6e435b1 100644 --- a/src/BooleanFilter.php +++ b/src/BooleanFilter.php @@ -8,7 +8,6 @@ abstract class BooleanFilter extends Filter { public $type = 'boolean'; - public function resolve(RestifyRequest $request, $filter) { $keyValues = collect($this->options($request))->mapWithKeys(function ($key) use ($filter) { diff --git a/src/Repositories/Repository.php b/src/Repositories/Repository.php index e16108ef9..79bfc648a 100644 --- a/src/Repositories/Repository.php +++ b/src/Repositories/Repository.php @@ -207,8 +207,6 @@ public function filters(RestifyRequest $request) return []; } - - /** * @param RestifyRequest $request * @return FieldCollection @@ -695,7 +693,7 @@ public static function uriTo(Model $model) public function availableFilters(RestifyRequest $request) { - return collect($this->filter($this->filters($request)))->each(fn(Filter $filter) => $filter->authorizedToSee($request)) + return collect($this->filter($this->filters($request)))->each(fn (Filter $filter) => $filter->authorizedToSee($request)) ->values(); } } diff --git a/src/SelectFilter.php b/src/SelectFilter.php index 6c99102ac..4a43c7235 100644 --- a/src/SelectFilter.php +++ b/src/SelectFilter.php @@ -5,5 +5,4 @@ abstract class SelectFilter extends Filter { public $type = 'select'; - } diff --git a/src/Services/Search/RepositorySearchService.php b/src/Services/Search/RepositorySearchService.php index 6ed373bae..ee4542f90 100644 --- a/src/Services/Search/RepositorySearchService.php +++ b/src/Services/Search/RepositorySearchService.php @@ -27,7 +27,7 @@ public function prepareMatchFields(RestifyRequest $request, $query, $extra = []) { $model = $query->getModel(); foreach ($this->repository->getMatchByFields() as $key => $type) { - if (!$request->has($key) && !data_get($extra, "match.$key")) { + if (! $request->has($key) && ! data_get($extra, "match.$key")) { continue; } @@ -60,7 +60,7 @@ public function prepareMatchFields(RestifyRequest $request, $query, $extra = []) case RestifySearchable::MATCH_INTEGER: case 'number': case 'int': - $query->where($field, '=', (int)$match); + $query->where($field, '=', (int) $match); break; } } @@ -125,7 +125,7 @@ public function prepareSearchFields(RestifyRequest $request, $query, $extra = [] $likeOperator = $connectionType == 'pgsql' ? 'ilike' : 'like'; foreach ($this->repository->getSearchableFields() as $column) { - $query->orWhere($model->qualifyColumn($column), $likeOperator, '%' . $search . '%'); + $query->orWhere($model->qualifyColumn($column), $likeOperator, '%'.$search.'%'); } }); @@ -176,12 +176,12 @@ public function setOrder($query, $param) protected function applyIndexQuery(RestifyRequest $request, Repository $repository) { - return fn($query) => $repository::indexQuery($request, $query); + return fn ($query) => $repository::indexQuery($request, $query); } protected function applyFilters(RestifyRequest $request, Repository $repository, $query) { - if (!empty($request->filters)) { + if (! empty($request->filters)) { $filters = json_decode(base64_decode($request->filters), true); collect($filters) @@ -191,21 +191,20 @@ protected function applyFilters(RestifyRequest $request, Repository $repository, return $filter['class'] === $availableFilter->key(); }); - if (is_null($matchingFilter)) { return false; } - if ($matchingFilter->invalidPayloadValue($request, $filter['value'])) { + if ($matchingFilter->invalidPayloadValue($request, $filter['value'])) { return false; - }; + } $matchingFilter->resolve($request, $filter['value']); return $matchingFilter; }) ->filter() - ->each(fn(Filter $filter) => $filter->filter($request, $query, $filter->value)); + ->each(fn (Filter $filter) => $filter->filter($request, $query, $filter->value)); } return $query; diff --git a/tests/Controllers/RepositoryFilterControllerTest.php b/tests/Controllers/RepositoryFilterControllerTest.php index 1e5ff5901..e174c8796 100644 --- a/tests/Controllers/RepositoryFilterControllerTest.php +++ b/tests/Controllers/RepositoryFilterControllerTest.php @@ -24,8 +24,8 @@ public function test_can_get_available_filters() public function test_the_boolean_filter_is_applied() { - factory(Post::class)->create(['is_active' => false,]); - factory(Post::class)->create(['is_active' => true,]); + factory(Post::class)->create(['is_active' => false]); + factory(Post::class)->create(['is_active' => true]); $filters = base64_encode(json_encode([ [ @@ -33,12 +33,12 @@ public function test_the_boolean_filter_is_applied() 'value' => [ 'is_active' => false, ], - ] + ], ])); $response = $this ->withoutExceptionHandling() - ->getJson('restify-api/posts?filters=' . $filters) + ->getJson('restify-api/posts?filters='.$filters) ->dump() ->assertStatus(200); @@ -47,19 +47,19 @@ public function test_the_boolean_filter_is_applied() public function test_the_select_filter_is_applied() { - factory(Post::class)->create(['category' => 'movie',]); - factory(Post::class)->create(['category' => 'article',]); + factory(Post::class)->create(['category' => 'movie']); + factory(Post::class)->create(['category' => 'article']); $filters = base64_encode(json_encode([ [ 'class' => SelectCategoryFilter::class, - 'value' => 'article' - ] + 'value' => 'article', + ], ])); $response = $this ->withExceptionHandling() - ->getJson('restify-api/posts?filters=' . $filters) + ->getJson('restify-api/posts?filters='.$filters) ->assertStatus(200); $this->assertCount(1, $response->json('data')); @@ -67,8 +67,8 @@ public function test_the_select_filter_is_applied() public function test_the_timestamp_filter_is_applied() { - factory(Post::class)->create(['created_at' => now()->addYear(),]); - factory(Post::class)->create(['created_at' => now()->subYear(),]); + factory(Post::class)->create(['created_at' => now()->addYear()]); + factory(Post::class)->create(['created_at' => now()->subYear()]); $filters = base64_encode(json_encode([ [ @@ -78,12 +78,12 @@ public function test_the_timestamp_filter_is_applied() [ 'class' => CreatedAfterDateFilter::class, 'value' => now()->addWeek()->timestamp, - ] + ], ])); $response = $this ->withExceptionHandling() - ->getJson('restify-api/posts?filters=' . $filters) + ->getJson('restify-api/posts?filters='.$filters) ->dump() ->assertStatus(200); diff --git a/tests/Fixtures/Post/PostRepository.php b/tests/Fixtures/Post/PostRepository.php index 5dd52427a..8c607079d 100644 --- a/tests/Fixtures/Post/PostRepository.php +++ b/tests/Fixtures/Post/PostRepository.php @@ -53,7 +53,7 @@ public function fieldsForStore(RestifyRequest $request) public function filters(RestifyRequest $request) { return [ - ActiveBooleanFilter::new()->canSee(fn() => true), + ActiveBooleanFilter::new()->canSee(fn () => true), SelectCategoryFilter::new(), CreatedAfterDateFilter::new(), ]; From 0af8d22f678c2e6b425548603a6d3dc2e50b9066 Mon Sep 17 00:00:00 2001 From: Eduard Lupacescu Date: Tue, 12 May 2020 09:31:27 +0300 Subject: [PATCH 3/4] fix --- src/Filter.php | 2 +- tests/Controllers/RepositoryFilterControllerTest.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Filter.php b/src/Filter.php index 927a6b8f3..d3ef8f407 100644 --- a/src/Filter.php +++ b/src/Filter.php @@ -70,7 +70,7 @@ public function invalidPayloadValue(Request $request, $value) public function resolve(RestifyRequest $request, $filter) { - $this->value = $filter['value']; + $this->value = $filter; } public function jsonSerialize() diff --git a/tests/Controllers/RepositoryFilterControllerTest.php b/tests/Controllers/RepositoryFilterControllerTest.php index 1e5ff5901..bbe98b7df 100644 --- a/tests/Controllers/RepositoryFilterControllerTest.php +++ b/tests/Controllers/RepositoryFilterControllerTest.php @@ -84,7 +84,6 @@ public function test_the_timestamp_filter_is_applied() $response = $this ->withExceptionHandling() ->getJson('restify-api/posts?filters=' . $filters) - ->dump() ->assertStatus(200); $this->assertCount(1, $response->json('data')); From cbddcec20af8ee0eb25ef35e9d5467058d14cda2 Mon Sep 17 00:00:00 2001 From: Lupacescu Eduard Date: Tue, 12 May 2020 09:32:20 +0300 Subject: [PATCH 4/4] Apply fixes from StyleCI (#177) --- .../RepositoryFilterControllerTest.php | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/Controllers/RepositoryFilterControllerTest.php b/tests/Controllers/RepositoryFilterControllerTest.php index bbe98b7df..f5c535799 100644 --- a/tests/Controllers/RepositoryFilterControllerTest.php +++ b/tests/Controllers/RepositoryFilterControllerTest.php @@ -24,8 +24,8 @@ public function test_can_get_available_filters() public function test_the_boolean_filter_is_applied() { - factory(Post::class)->create(['is_active' => false,]); - factory(Post::class)->create(['is_active' => true,]); + factory(Post::class)->create(['is_active' => false]); + factory(Post::class)->create(['is_active' => true]); $filters = base64_encode(json_encode([ [ @@ -33,12 +33,12 @@ public function test_the_boolean_filter_is_applied() 'value' => [ 'is_active' => false, ], - ] + ], ])); $response = $this ->withoutExceptionHandling() - ->getJson('restify-api/posts?filters=' . $filters) + ->getJson('restify-api/posts?filters='.$filters) ->dump() ->assertStatus(200); @@ -47,19 +47,19 @@ public function test_the_boolean_filter_is_applied() public function test_the_select_filter_is_applied() { - factory(Post::class)->create(['category' => 'movie',]); - factory(Post::class)->create(['category' => 'article',]); + factory(Post::class)->create(['category' => 'movie']); + factory(Post::class)->create(['category' => 'article']); $filters = base64_encode(json_encode([ [ 'class' => SelectCategoryFilter::class, - 'value' => 'article' - ] + 'value' => 'article', + ], ])); $response = $this ->withExceptionHandling() - ->getJson('restify-api/posts?filters=' . $filters) + ->getJson('restify-api/posts?filters='.$filters) ->assertStatus(200); $this->assertCount(1, $response->json('data')); @@ -67,8 +67,8 @@ public function test_the_select_filter_is_applied() public function test_the_timestamp_filter_is_applied() { - factory(Post::class)->create(['created_at' => now()->addYear(),]); - factory(Post::class)->create(['created_at' => now()->subYear(),]); + factory(Post::class)->create(['created_at' => now()->addYear()]); + factory(Post::class)->create(['created_at' => now()->subYear()]); $filters = base64_encode(json_encode([ [ @@ -78,12 +78,12 @@ public function test_the_timestamp_filter_is_applied() [ 'class' => CreatedAfterDateFilter::class, 'value' => now()->addWeek()->timestamp, - ] + ], ])); $response = $this ->withExceptionHandling() - ->getJson('restify-api/posts?filters=' . $filters) + ->getJson('restify-api/posts?filters='.$filters) ->assertStatus(200); $this->assertCount(1, $response->json('data'));