Skip to content

Commit 5753e3a

Browse files
committed
Expose scope and filter as public API
1 parent 848a8df commit 5753e3a

File tree

2 files changed

+78
-73
lines changed

2 files changed

+78
-73
lines changed

src/Endpoint/Index.php

Lines changed: 6 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,12 @@
1717
use JsonApiPhp\JsonApi\Link\PrevLink;
1818
use Psr\Http\Message\ResponseInterface;
1919
use Psr\Http\Message\ServerRequestInterface as Request;
20-
use Tobyz\JsonApiServer\Adapter\AdapterInterface;
20+
use Tobyz\JsonApiServer\Context;
2121
use Tobyz\JsonApiServer\Exception\BadRequestException;
2222
use Tobyz\JsonApiServer\Exception\ForbiddenException;
2323
use Tobyz\JsonApiServer\JsonApi;
2424
use Tobyz\JsonApiServer\ResourceType;
2525
use Tobyz\JsonApiServer\Schema\Attribute;
26-
use Tobyz\JsonApiServer\Context;
27-
use Tobyz\JsonApiServer\Schema\HasMany;
28-
use Tobyz\JsonApiServer\Schema\HasOne;
2926
use Tobyz\JsonApiServer\Schema\Meta;
3027
use Tobyz\JsonApiServer\Serializer;
3128
use function Tobyz\JsonApiServer\evaluate;
@@ -59,13 +56,16 @@ public function handle(Context $context): ResponseInterface
5956

6057
$query = $adapter->newQuery($context);
6158

62-
run_callbacks($schema->getListeners('scope'), [$query, $context]);
59+
$this->resource->scope($query, $context);
6360

6461
$include = $this->getInclude($context);
6562

6663
[$offset, $limit] = $this->paginate($query, $context);
6764
$this->sort($query, $context);
68-
$this->filter($query, $context);
65+
66+
if ($filter = $context->getRequest()->getQueryParams()['filter'] ?? null) {
67+
$this->resource->filter($query, $filter, $context);
68+
}
6969

7070
run_callbacks($schema->getListeners('listing'), [$query, $context]);
7171

@@ -234,71 +234,4 @@ private function paginate($query, Context $context)
234234

235235
return [$offset, $limit];
236236
}
237-
238-
private function filter($query, Context $context)
239-
{
240-
if (! $filter = $context->getRequest()->getQueryParams()['filter'] ?? null) {
241-
return;
242-
}
243-
244-
if (! is_array($filter)) {
245-
throw new BadRequestException('filter must be an array', 'filter');
246-
}
247-
248-
$schema = $this->resource->getSchema();
249-
$adapter = $this->resource->getAdapter();
250-
$filters = $schema->getFilters();
251-
$fields = $schema->getFields();
252-
253-
foreach ($filter as $name => $value) {
254-
if ($name === 'id') {
255-
$adapter->filterByIds($query, explode(',', $value));
256-
continue;
257-
}
258-
259-
if (isset($filters[$name]) && evaluate($filters[$name]->getVisible(), [$context])) {
260-
$filters[$name]->getCallback()($query, $value, $context);
261-
continue;
262-
}
263-
264-
if (isset($fields[$name]) && evaluate($fields[$name]->getFilterable(), [$context])) {
265-
if ($fields[$name] instanceof Attribute) {
266-
$this->filterByAttribute($adapter, $query, $fields[$name], $value);
267-
} elseif ($fields[$name] instanceof HasOne) {
268-
$value = array_filter(explode(',', $value));
269-
$adapter->filterByHasOne($query, $fields[$name], $value);
270-
} elseif ($fields[$name] instanceof HasMany) {
271-
$value = array_filter(explode(',', $value));
272-
$adapter->filterByHasMany($query, $fields[$name], $value);
273-
}
274-
continue;
275-
}
276-
277-
throw new BadRequestException("Invalid filter [$name]", "filter[$name]");
278-
}
279-
}
280-
281-
private function filterByAttribute(AdapterInterface $adapter, $query, Attribute $attribute, $value)
282-
{
283-
if (preg_match('/(.+)\.\.(.+)/', $value, $matches)) {
284-
if ($matches[1] !== '*') {
285-
$adapter->filterByAttribute($query, $attribute, $value, '>=');
286-
}
287-
if ($matches[2] !== '*') {
288-
$adapter->filterByAttribute($query, $attribute, $value, '<=');
289-
}
290-
291-
return;
292-
}
293-
294-
foreach (['>=', '>', '<=', '<'] as $operator) {
295-
if (strpos($value, $operator) === 0) {
296-
$adapter->filterByAttribute($query, $attribute, substr($value, strlen($operator)), $operator);
297-
298-
return;
299-
}
300-
}
301-
302-
$adapter->filterByAttribute($query, $attribute, $value);
303-
}
304237
}

src/ResourceType.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
namespace Tobyz\JsonApiServer;
1313

1414
use Tobyz\JsonApiServer\Adapter\AdapterInterface;
15+
use Tobyz\JsonApiServer\Exception\BadRequestException;
16+
use Tobyz\JsonApiServer\Schema\Attribute;
17+
use Tobyz\JsonApiServer\Schema\HasMany;
18+
use Tobyz\JsonApiServer\Schema\HasOne;
1519
use Tobyz\JsonApiServer\Schema\Type;
1620

1721
final class ResourceType
@@ -50,4 +54,72 @@ public function getSchema(): Type
5054

5155
return $this->schema;
5256
}
57+
58+
public function scope($query, Context $context)
59+
{
60+
run_callbacks($this->getSchema()->getListeners('scope'), [$query, $context]);
61+
}
62+
63+
public function filter($query, $filter, Context $context)
64+
{
65+
if (! is_array($filter)) {
66+
throw new BadRequestException('filter must be an array', 'filter');
67+
}
68+
69+
$schema = $this->getSchema();
70+
$adapter = $this->getAdapter();
71+
$filters = $schema->getFilters();
72+
$fields = $schema->getFields();
73+
74+
foreach ($filter as $name => $value) {
75+
if ($name === 'id') {
76+
$adapter->filterByIds($query, explode(',', $value));
77+
continue;
78+
}
79+
80+
if (isset($filters[$name]) && evaluate($filters[$name]->getVisible(), [$context])) {
81+
$filters[$name]->getCallback()($query, $value, $context);
82+
continue;
83+
}
84+
85+
if (isset($fields[$name]) && evaluate($fields[$name]->getFilterable(), [$context])) {
86+
if ($fields[$name] instanceof Attribute) {
87+
$this->filterByAttribute($adapter, $query, $fields[$name], $value);
88+
} elseif ($fields[$name] instanceof HasOne) {
89+
$value = array_filter(explode(',', $value));
90+
$adapter->filterByHasOne($query, $fields[$name], $value);
91+
} elseif ($fields[$name] instanceof HasMany) {
92+
$value = array_filter(explode(',', $value));
93+
$adapter->filterByHasMany($query, $fields[$name], $value);
94+
}
95+
continue;
96+
}
97+
98+
throw new BadRequestException("Invalid filter [$name]", "filter[$name]");
99+
}
100+
}
101+
102+
private function filterByAttribute(AdapterInterface $adapter, $query, Attribute $attribute, $value)
103+
{
104+
if (preg_match('/(.+)\.\.(.+)/', $value, $matches)) {
105+
if ($matches[1] !== '*') {
106+
$adapter->filterByAttribute($query, $attribute, $value, '>=');
107+
}
108+
if ($matches[2] !== '*') {
109+
$adapter->filterByAttribute($query, $attribute, $value, '<=');
110+
}
111+
112+
return;
113+
}
114+
115+
foreach (['>=', '>', '<=', '<'] as $operator) {
116+
if (strpos($value, $operator) === 0) {
117+
$adapter->filterByAttribute($query, $attribute, substr($value, strlen($operator)), $operator);
118+
119+
return;
120+
}
121+
}
122+
123+
$adapter->filterByAttribute($query, $attribute, $value);
124+
}
53125
}

0 commit comments

Comments
 (0)