From 1f80406a710f3b4cf7c35c84843572e444387b95 Mon Sep 17 00:00:00 2001 From: Martin Kiesel Date: Sun, 30 Sep 2018 16:43:23 +0200 Subject: [PATCH] Implement applying default filters - #10 --- src/Filter.php | 21 ++++++++++++++++- src/FilterContract.php | 17 ++++++++++++++ src/helpers.php | 24 ++++++++++++++++++++ tests/DefaultFilterTest.php | 45 +++++++++++++++++++++++++++++++++++++ tests/TestCase.php | 5 ++++- 5 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 tests/DefaultFilterTest.php diff --git a/src/Filter.php b/src/Filter.php index 9c80352..0b7084c 100644 --- a/src/Filter.php +++ b/src/Filter.php @@ -44,6 +44,25 @@ public function apply(Builder $builder): Builder } + public function default(array $defaults, int $code = 307) + { + if ($this->request->isMethod('GET') || ! empty($defaults)) { + $defaults = force_assoc_array($defaults, ''); + + $append = []; + foreach ($defaults as $filter => $default) { + if ( ! $this->request->has($filter)) { + $append[$filter] = $default; + } + } + + if ( ! empty($append)) { + abort(redirect($this->request->fullUrlWithQuery($append), $code)); + } + } + } + + /** * @return \Illuminate\Database\Eloquent\Builder */ @@ -107,7 +126,7 @@ private function filters(): array foreach ($this->filterMap as $filter => $value) { $method = (is_string($filter)) ? $filter : $value; - // head([]) === false, we check if head returns false and remove that item from array + // head([]) === false, we check if head returns false and remove that item from array, I am sorry if (($filters[$method] = head($this->request->only($value))) === false) { unset($filters[$method]); } diff --git a/src/FilterContract.php b/src/FilterContract.php index 0735c0a..0c5f300 100644 --- a/src/FilterContract.php +++ b/src/FilterContract.php @@ -7,9 +7,26 @@ interface FilterContract { + /** + * Applies filters on a $builder instance. + * + * @param \Illuminate\Database\Eloquent\Builder $builder + * + * @return \Illuminate\Database\Eloquent\Builder + */ function apply(Builder $builder); + /** + * @param array $defaults + * + * @param int $code + * + * @return void + */ + function default(array $defaults, int $code = 307); + + /** * @return array ex: ['method-name', 'another-method' => 'alias', 'yet-another-method' => ['alias-one', 'alias-two]] */ diff --git a/src/helpers.php b/src/helpers.php index 0680d59..5a5e99b 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -15,3 +15,27 @@ function remove_prefix($prefix, $subject, $check = true) return $check ? str_replace_first($prefix, '', $subject) : substr($subject, strlen($prefix)); } } + +if ( ! function_exists('force_assoc_array')) { + /** + * Transforms array to be associative. + * + * @param array $array + * @param null $empty + * + * @return array + */ + function force_assoc_array(array $array, $empty = null) + { + $new = []; + foreach ($array as $key => $value) { + if (is_numeric($key)) { + $new[$value] = $empty; + } else { + $new[$key] = $value; + } + } + + return $new; + } +} diff --git a/tests/DefaultFilterTest.php b/tests/DefaultFilterTest.php new file mode 100644 index 0000000..599a422 --- /dev/null +++ b/tests/DefaultFilterTest.php @@ -0,0 +1,45 @@ +expectException(\Illuminate\Http\Exceptions\HttpResponseException::class); + $filter = $this->buildCustomFilter('one=neo'); + + $filter->default(['trinity']); + } + + + function test_redirect_does_not_happen() + { + $filter = $this->buildCustomFilter('one=neo&side-kick=trinity'); + + $filter->default(['side-kick' => 'tank']); + + $this->assertTrue(true, 'We are testing, that \Illuminate\Http\Exceptions\HttpResponseException is not thrown'); + } + + + function test_defaults_redirect_with_correct_query() + { + $filter = $this->buildCustomFilter('one=neo'); + + try { + $code = 307; + $filter->default(['trinity', 'morpheus'], $code); + } catch (\Illuminate\Http\Exceptions\HttpResponseException $e) { + $response = $e->getResponse(); + + $this->assertEquals($response->getStatusCode(), $code); + $this->assertTrue($response->isRedirection()); + + $parameters = []; + parse_str(parse_url($response->headers->get('location'), PHP_URL_QUERY), $parameters); + $this->assertArraySubset($parameters, ['one' => 'neo', 'trinity' => '', 'morpheus' => '']); + } + } +} \ No newline at end of file diff --git a/tests/TestCase.php b/tests/TestCase.php index 764d482..191cdc6 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -6,8 +6,8 @@ use Illuminate\Http\Request; use Kyslik\LaravelFilterable\FilterableServiceProvider; use Kyslik\LaravelFilterable\Generic\Templater; -use Kyslik\LaravelFilterable\Test\Stubs\UserFilter; use Kyslik\LaravelFilterable\Test\Stubs\RoleFilter; +use Kyslik\LaravelFilterable\Test\Stubs\UserFilter; use Orchestra\Testbench\TestCase as Orchestra; abstract class TestCase extends Orchestra @@ -50,6 +50,7 @@ protected function buildFilter($requestQuery) /** @var Request $request */ $request = resolve(Request::class)->create('http://test.dev?'.$requestQuery); + $this->app->instance(Request::class, $request); return new UserFilter($request, resolve(Templater::class)); } @@ -59,6 +60,8 @@ protected function buildCustomFilter($requestQuery) { /** @var Request $request */ $request = resolve(Request::class)->create('http://test.dev?'.$requestQuery); + $this->app->instance(Request::class, $request); + return new RoleFilter($request); }