Skip to content

Commit 843e13f

Browse files
authored
Filter definition. (#310)
* Return repository key on filters. * Apply fixes from StyleCI (#307) * Adding filter definition. * Apply fixes from StyleCI (#308) * docs * Map into qualified classes. * Apply fixes from StyleCI (#309) * wip
1 parent 278984d commit 843e13f

16 files changed

+509
-185
lines changed

docs/docs/4.0/search/search.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,38 @@ So now you can query this:
154154
GET: /api/restify/users?is_active=true
155155
```
156156

157+
### Match definition
158+
159+
You can implement a match filter definition, and specify for example related repository:
160+
161+
```php
162+
public static $match = [
163+
'title' => 'string',
164+
'user_id' => MatchFilter::make()
165+
->setType('int')
166+
->setRelatedRepositoryKey(UserRepository::uriKey()),
167+
];
168+
```
169+
When you will list this filter (with `posts/filters?only=matches`), you will get:
170+
171+
```json
172+
{
173+
"class": "Binaryk\LaravelRestify\Filters\MatchFilter"
174+
"key": "matches"
175+
"type": "string"
176+
"column": "title"
177+
"options": []
178+
},
179+
{
180+
"class": "Binaryk\LaravelRestify\Filters\MatchFilter"
181+
"key": "matches"
182+
"type": "int"
183+
"column": "user_id"
184+
"options": []
185+
"related_repository_key": "users"
186+
"related_repository_url": "//users"
187+
}
188+
```
157189
## Sort
158190
When index query entities, usually we have to sort by specific attributes.
159191

src/Commands/FilterCommand.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
namespace Binaryk\LaravelRestify\Commands;
4+
5+
use Illuminate\Console\ConfirmableTrait;
6+
use Illuminate\Console\GeneratorCommand;
7+
use Illuminate\Support\Str;
8+
9+
class FilterCommand extends GeneratorCommand
10+
{
11+
use ConfirmableTrait;
12+
13+
protected $name = 'restify:filter';
14+
15+
protected $description = 'Create a new filter class';
16+
17+
protected $type = 'Filter';
18+
19+
public function handle()
20+
{
21+
if (parent::handle() === false && ! $this->option('force')) {
22+
return false;
23+
}
24+
}
25+
26+
/**
27+
* Build the class with the given name.
28+
* This method should return the file class content.
29+
*
30+
* @param string $name
31+
* @return string
32+
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
33+
*/
34+
protected function buildClass($name)
35+
{
36+
if (false === Str::endsWith($name, 'Filter')) {
37+
$name .= 'Filter';
38+
}
39+
40+
return tap(parent::buildClass($name), function ($stub) use ($name) {
41+
return str_replace(['{{ attribute }}', '{{ query }}'], Str::snake(
42+
Str::beforeLast(class_basename($name), 'Filter')
43+
), $stub);
44+
});
45+
}
46+
47+
protected function getStub()
48+
{
49+
return __DIR__.'/stubs/filter.stub';
50+
}
51+
52+
protected function getPath($name)
53+
{
54+
if (false === Str::endsWith($name, 'Filter')) {
55+
$name .= 'Filter';
56+
}
57+
58+
return parent::getPath($name);
59+
}
60+
61+
protected function getDefaultNamespace($rootNamespace)
62+
{
63+
return $rootNamespace.'\Restify\Matchers';
64+
}
65+
}

src/Commands/stubs/filter.stub

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace DummyNamespace;
4+
5+
use Binaryk\LaravelRestify\Filter;
6+
use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
7+
8+
class DummyClass extends Filter
9+
{
10+
public function filter(RestifyRequest $request, $query, $value)
11+
{
12+
// $query->where('{{ attribute }}', $request->input('{{ query }}'));
13+
}
14+
}

src/Filter.php

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Binaryk\LaravelRestify;
44

55
use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
6+
use Binaryk\LaravelRestify\Repositories\Repository;
67
use Binaryk\LaravelRestify\Traits\Make;
78
use Closure;
89
use Illuminate\Http\Request;
@@ -15,12 +16,18 @@ abstract class Filter implements JsonSerializable
1516

1617
public $type = 'value';
1718

19+
public $column;
20+
1821
public $value;
1922

2023
public $canSeeCallback;
2124

2225
public static $uriKey;
2326

27+
public $relatedRepositoryKey;
28+
29+
public Repository $repository;
30+
2431
public function __construct()
2532
{
2633
$this->booted();
@@ -55,6 +62,25 @@ protected function getType()
5562
return $this->type;
5663
}
5764

65+
public function getColumn(): ?string
66+
{
67+
return $this->column;
68+
}
69+
70+
public function setColumn(string $column): self
71+
{
72+
$this->column = $column;
73+
74+
return $this;
75+
}
76+
77+
public function setType(string $type): self
78+
{
79+
$this->type = $type;
80+
81+
return $this;
82+
}
83+
5884
public function options(Request $request)
5985
{
6086
// noop
@@ -76,6 +102,36 @@ public function resolve(RestifyRequest $request, $filter)
76102
$this->value = $filter;
77103
}
78104

105+
public function getRelatedRepositoryKey(): ?string
106+
{
107+
return $this->relatedRepositoryKey;
108+
}
109+
110+
public function setRelatedRepositoryKey(string $repositoryKey): self
111+
{
112+
$this->relatedRepositoryKey = $repositoryKey;
113+
114+
return $this;
115+
}
116+
117+
public function setRepository(Repository $repository): self
118+
{
119+
$this->repository = $repository;
120+
121+
return $this;
122+
}
123+
124+
public function getRelatedRepositoryUrl(): ?string
125+
{
126+
return ($key = $this->getRelatedRepositoryKey())
127+
? with(Restify::repositoryForKey($key), function ($repository = null) {
128+
if (is_subclass_of($repository, Repository::class)) {
129+
return Restify::path($repository::uriKey());
130+
}
131+
})
132+
: null;
133+
}
134+
79135
/**
80136
* Get the URI key for the filter.
81137
*
@@ -87,24 +143,28 @@ public static function uriKey()
87143
return static::$uriKey;
88144
}
89145

90-
$kebabWithoutRepository = Str::kebab(Str::replaceLast('Filter', '', class_basename(get_called_class())));
146+
$kebabWithoutFilter = Str::kebab(Str::replaceLast('Filter', '', class_basename(get_called_class())));
91147

92-
/**
93-
* e.g. UserRepository => users
94-
* e.g. LaravelEntityRepository => laravel-entities.
95-
*/
96-
return Str::plural($kebabWithoutRepository);
148+
return Str::plural($kebabWithoutFilter);
97149
}
98150

99151
public function jsonSerialize()
100152
{
101-
return [
153+
return with([
102154
'class' => static::class,
103155
'key' => static::uriKey(),
104156
'type' => $this->getType(),
157+
'column' => $this->getColumn(),
105158
'options' => collect($this->options(app(Request::class)))->map(function ($value, $key) {
106159
return is_array($value) ? ($value + ['property' => $key]) : ['label' => $key, 'property' => $value];
107160
})->values()->all(),
108-
];
161+
], function (array $initial) {
162+
return $this->relatedRepositoryKey
163+
? array_merge($initial, [
164+
'related_repository_key' => $this->getRelatedRepositoryKey(),
165+
'related_repository_url' => $this->getRelatedRepositoryUrl(),
166+
])
167+
: $initial;
168+
});
109169
}
110170
}

src/Filters/FilterDefinition.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace Binaryk\LaravelRestify\Filters;
4+
5+
use Binaryk\LaravelRestify\Repositories\Repository;
6+
use Binaryk\LaravelRestify\Restify;
7+
use JsonSerializable;
8+
9+
abstract class FilterDefinition implements JsonSerializable
10+
{
11+
public static string $type = 'string';
12+
13+
public static string $relatedRepositoryKey;
14+
15+
public function getType(): string
16+
{
17+
return static::$type;
18+
}
19+
20+
public function getRelatedRepositoryKey(): ?string
21+
{
22+
return static::$relatedRepositoryKey;
23+
}
24+
25+
public function getRelatedRepositoryUrl(): ?string
26+
{
27+
return ($key = $this->getRelatedRepositoryKey())
28+
? with(Restify::repositoryForKey($key), function ($repository = null) {
29+
if (is_subclass_of($repository, Repository::class)) {
30+
return Restify::path($repository::uriKey());
31+
}
32+
})
33+
: null;
34+
}
35+
36+
public function jsonSerialize()
37+
{
38+
return with([
39+
'type' => $this->getType(),
40+
], function (array $initial) {
41+
return static::$relatedRepositoryKey
42+
? array_merge($initial, [
43+
'related_repository_key' => $this->getRelatedRepositoryKey(),
44+
'related_repository_url' => $this->getRelatedRepositoryUrl(),
45+
])
46+
: $initial;
47+
});
48+
}
49+
}

0 commit comments

Comments
 (0)