Skip to content

Commit bad98dc

Browse files
committed
WIP add resource action endpoint
1 parent f8c617c commit bad98dc

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed

src/Endpoint/ResourceAction.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<?php
2+
3+
namespace Tobyz\JsonApiServer\Endpoint;
4+
5+
use Closure;
6+
use Psr\Http\Message\ResponseInterface;
7+
use Tobyz\JsonApiServer\Context;
8+
use Tobyz\JsonApiServer\Endpoint\Concerns\FindsResources;
9+
use Tobyz\JsonApiServer\Endpoint\Concerns\ShowsResources;
10+
use Tobyz\JsonApiServer\Exception\ForbiddenException;
11+
use Tobyz\JsonApiServer\Exception\MethodNotAllowedException;
12+
use Tobyz\JsonApiServer\JsonApi;
13+
use Tobyz\JsonApiServer\OpenApi\OpenApiPathsProvider;
14+
use Tobyz\JsonApiServer\Resource\Collection;
15+
use Tobyz\JsonApiServer\Schema\Concerns\HasDescription;
16+
use Tobyz\JsonApiServer\Schema\Concerns\HasVisibility;
17+
18+
use function Tobyz\JsonApiServer\json_api_response;
19+
20+
class ResourceAction implements Endpoint, OpenApiPathsProvider
21+
{
22+
use HasVisibility;
23+
use HasDescription;
24+
use FindsResources;
25+
use ShowsResources;
26+
27+
public string $method = 'POST';
28+
29+
public function __construct(public string $name, public Closure $handler)
30+
{
31+
}
32+
33+
public static function make(string $name, Closure $handler): static
34+
{
35+
return new static($name, $handler);
36+
}
37+
38+
public function method(string $method): static
39+
{
40+
$this->method = strtoupper($method);
41+
42+
return $this;
43+
}
44+
45+
public function handle(Context $context): ?ResponseInterface
46+
{
47+
$segments = explode('/', $context->path());
48+
49+
if (count($segments) !== 3 || $segments[2] !== $this->name) {
50+
return null;
51+
}
52+
53+
if ($context->request->getMethod() !== $this->method) {
54+
throw new MethodNotAllowedException();
55+
}
56+
57+
$model = $this->findResource($context, $segments[1]);
58+
59+
$context = $context
60+
->withModel($model)
61+
->withResource($context->resource($context->collection->resource($model, $context)));
62+
63+
if (!$this->isVisible($context)) {
64+
throw new ForbiddenException();
65+
}
66+
67+
($this->handler)($model, $context);
68+
69+
return json_api_response($this->showResource($context, $model));
70+
}
71+
72+
public function getOpenApiPaths(Collection $collection): array
73+
{
74+
$resources = array_map(
75+
fn($resource) => [
76+
'$ref' => "#/components/schemas/$resource",
77+
],
78+
$collection->resources(),
79+
);
80+
81+
return [
82+
"/{$collection->name()}/{id}/{$this->name}" => [
83+
strtolower($this->method) => [
84+
'description' => $this->getDescription(),
85+
'tags' => [$collection->name()],
86+
'parameters' => [
87+
[
88+
'name' => 'id',
89+
'in' => 'path',
90+
'required' => true,
91+
'schema' => ['type' => 'string'],
92+
],
93+
],
94+
'responses' => [
95+
'200' => [
96+
'content' => [
97+
JsonApi::MEDIA_TYPE => [
98+
'schema' => [
99+
'type' => 'object',
100+
'required' => ['data'],
101+
'properties' => [
102+
'data' =>
103+
count($resources) === 1
104+
? $resources[0]
105+
: ['oneOf' => $resources],
106+
],
107+
],
108+
],
109+
],
110+
],
111+
],
112+
],
113+
],
114+
];
115+
}
116+
}

0 commit comments

Comments
 (0)