8000 add wiring for fetch many · laravel-json-api/laravel@48d9110 · GitHub
[go: up one dir, main page]

Skip to content

Commit 48d9110

Browse files
committed
add wiring for fetch many
1 parent 02431a3 commit 48d9110

File tree

7 files changed

+327
-48
lines changed

7 files changed

+327
-48
lines changed

src/Http/Controllers/Actions/FetchMany.php

Lines changed: 10 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -19,48 +19,23 @@
1919

2020
namespace LaravelJsonApi\Laravel\Http\Controllers\Actions;
2121

22-
use Illuminate\Contracts\Support\Responsable;
23-
use Illuminate\Http\Response;
24-
use LaravelJsonApi\Contracts\Routing\Route;
25-
use LaravelJsonApi\Contracts\Store\Store as StoreContract;
22+
use LaravelJsonApi\Contracts\Http\Actions\FetchMany as FetchManyContract;
2623
use LaravelJsonApi\Core\Responses\DataResponse;
27-
use LaravelJsonApi\Laravel\Http\Requests\ResourceQuery;
24+
use LaravelJsonApi\Laravel\Http\Requests\JsonApiRequest;
2825

2926
trait FetchMany
3027
{
31-
3228
/**
33-
* Fetch zero to many JSON API resources.
29+
* Fetch zero-to-many JSON:API resources.
3430
*
35-
* @param Route $route
36-
* @param StoreContract $store
37-
* @return Responsable|Response
31+
* @param JsonApiRequest $request
32+
* @param FetchManyContract $action
33+
* @return DataResponse
3834
*/
39-
public function index(Route $route, StoreContract $store)
35+
public function index(JsonApiRequest $request, FetchManyContract $action): DataResponse
4036
{
41-
$request = ResourceQuery::queryMany(
42-
$resourceType = $route->resourceType()
43-
);
44-
45-
$response = null;
46-
47-
if (method_exists($this, 'searching')) {
48-
$response = $this->searching($request);
49-
}
50-
51-
if ($response) {
52-
return $response;
53-
}
54-
55-
$data = $store
56-
->queryAll($resourceType)
57-
->withRequest($request)
58-
->firstOrPaginate($request->page());
59-
60-
if (method_exists($this, 'searched')) {
61-
$response = $this->searched($data, $request);
62-
}
63-
64-
return $response ?: DataResponse::make($data)->withQueryParameters($request);
37+
return $action
38+
->withHooks($this)
39+
->execute($request);
6540
}
6641
}

src/Http/Controllers/Actions/FetchOne.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,23 @@
1919

2020
namespace LaravelJsonApi\Laravel\Http\Controllers\Actions;
2121

22-
use Illuminate\Contracts\Support\Responsable;
2322
use LaravelJsonApi\Contracts\Http\Actions\FetchOne as FetchOneContract;
24-
use LaravelJsonApi\Contracts\Routing\Route;
23+
use LaravelJsonApi\Core\Responses\DataResponse;
24+
use LaravelJsonApi\Laravel\Http\Requests\JsonApiRequest;
2525

2626
trait FetchOne
2727
{
2828
/**
2929
* Fetch zero to one JSON:API resource by id.
3030
*
31-
* @param Route $route
31+
* @param JsonApiRequest $request
3232
* @param FetchOneContract $action
33-
* @return Responsable
33+
* @return DataResponse
3434
*/
35-
public function show(Route $route, FetchOneContract $action): Responsable
35+
public function show(JsonApiRequest $request, FetchOneContract $action): DataResponse
3636
{
3737
return $action
38-
->withIdOrModel($route->modelOrResourceId())
39-
->withHooks($this);
38+
->withHooks($this)
39+
->execute($request);
4040
}
4141
}

src/Http/Controllers/Actions/Store.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,23 @@
1919

2020
namespace LaravelJsonApi\Laravel\Http\Controllers\Actions;
2121

22-
use Illuminate\Contracts\Support\Responsable;
23-
use LaravelJsonApi\Contracts\Http\Actions\Store as StoreAction;
22+
use LaravelJsonApi\Contracts\Http\Actions\Store as StoreContract;
23+
use LaravelJsonApi\Core\Responses\DataResponse;
24+
use LaravelJsonApi\Laravel\Http\Requests\JsonApiRequest;
2425

2526
trait Store
2627
{
2728
/**
2829
* Create a new resource.
2930
*
30-
* @param StoreAction $action
31-
* @return Responsable
31+
* @param JsonApiRequest $request
32+
* @param StoreContract $action
33+
* @return DataResponse
3234
*/
33-
public function store(StoreAction $action): Responsable
35+
public function store(JsonApiRequest $request, StoreContract $action): DataResponse
3436
{
3537
return $action
36-
->withHooks($this);
38+
->withHooks($this)
39+
->execute($request);
3740
}
3841
}

src/Http/Requests/JsonApiRequest.php

Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
<?php
2+
/*
3+
* Copyright 2023 Cloud Creativity Limited
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
declare(strict_types=1);
19+
20+
namespace LaravelJsonApi\Laravel\Http\Requests;
21+
22+
use Illuminate\Foundation\Http\FormRequest as BaseFormRequest;
23+
use Illuminate\Support\Str;
24+
use LaravelJsonApi\Core\JsonApiService;
25+
26+
class JsonApiRequest extends BaseFormRequest
27+
{
28+
/**
29+
* @var string
30+
*/
31+
public const JSON_API_MEDIA_TYPE = 'application/vnd.api+json';
32+
33+
/**
34+
* @return void
35+
*/
36+
public function validateResolved(): void
37+
{
38+
// no-op
39+
}
40+
41+
/**
42+
* @return bool
43+
*/
44+
public function wantsJsonApi(): bool
45+
{
46+
$acceptable = $this->getAcceptableContentTypes();
47+
48+
return isset($acceptable[0]) && self::JSON_API_MEDIA_TYPE === $acceptable[0];
49+
}
50+
51+
/**
52+
* @return bool
53+
*/
54+
public function acceptsJsonApi(): bool
55+
{
56+
return $this->accepts(self::JSON_API_MEDIA_TYPE);
57+
}
58+
59+
/**
60+
* Determine if the request is sending JSON API content.
61+
*
62+
* @return bool
63+
*/
64+
public function isJsonApi(): bool
65+
{
66+
return $this->matchesType(self::JSON_API_MEDIA_TYPE, $this->header('CONTENT_TYPE'));
67+
}
68+
69+
/**
70+
* Is this a request to view any resource? (Index action.)
71+
*
72+
* @return bool
73+
*/
74+
public function isViewingAny(): bool
75+
{
76+
return $this->isMethod('GET') && $this->doesntHaveResourceId() && $this->isNotRelationship();
77+
}
78+
79+
/**
80+
* Is this a request to view a specific resource? (Read action.)
81+
*
82+
* @return bool
83+
*/
84+
public function isViewingOne(): bool
85+
{
86+
return $this->isMethod('GET') && $this->hasResourceId() && $this->isNotRelationship();
87+
}
88+
89+
/**
90+
* Is this a request to view related resources in a relationship? (Show-related action.)
91+
*
92+
* @return bool
93+
*/
94+
public function isViewingRelated(): bool
95+
{
96+
return $this->isMethod('GET') && $this->isRelationship() && !$this->urlHasRelationships();
97+
}
98+
99+
/**
100+
* Is this a request to view resource identifiers in a relationship? (Show-relationship action.)
101+
*
102+
* @return bool
103+
*/
104+
public function isViewingRelationship(): bool
105+
{
106+
return $this->isMethod('GET') && $this->isRelationship() && $this->urlHasRelationships();
107+
}
108+
109+
/**
110+
* Is this a request to create a resource?
111+
*
112+
* @return bool
113+
*/
114+
public function isCreating(): bool
115+
{
116+
return $this->isMethod('POST') && $this->isNotRelationship();
117+
}
118+
119+
/**
120+
* Is this a request to update a resource?
121+
*
122+
* @return bool
123+
*/
124+
public function isUpdating(): bool
125+
{
126+
return $this->isMethod('PATCH') && $this->isNotRelationship();
127+
}
128+
129+
/**
130+
* Is this a request to create or update a resource?
131+
*
132+
* @return bool
133+
*/
134+
public function isCreatingOrUpdating(): bool
135+
{
136+
return $this->isCreating() || $this->isUpdating();
137+
}
138+
139+
/**
140+
* Is this a request to replace a resource relationship?
141+
*
142+
* @return bool
143+
*/
144+
public function isUpdatingRelationship(): bool
145+
{
146+
return $this->isMethod('PATCH') && $this->isRelationship();
147+
}
148+
149+
/**
150+
* Is this a request to attach records to a resource relationship?
151+
*
152+
* @return bool
153+
*/
154+
public function isAttachingRelationship(): bool
155+
{
156+
return $this->isMethod('POST') && $this->isRelationship();
157+
}
158+
159+
/**
160+
* Is this a request to detach records from a resource relationship?
161+
*
162+
* @return bool
163+
*/
164+
public function isDetachingRelationship(): bool
165+
{
166+
return $this->isMethod('DELETE') && $this->isRelationship();
167+
}
168+
169+
/**
170+
* Is this a request to modify a resource relationship?
171+
*
172+
* @return bool
173+
*/
174+
public function isModifyingRelationship(): bool
175+
{
176+
return $this->isUpdatingRelationship() ||
177+
$this->isAttachingRelationship() ||
178+
$this->isDetachingRelationship();
179+
}
180+
181+
/**
182+
* @return bool
183+
*/
184+
public function isDeleting(): bool
185+
{
186+
return $this->isMethod('DELETE') && $this->isNotRelationship();
187+
}
188+
189+
/**
190+
* Is this a request to view or modify a relationship?
191+
*
192+
* @return bool
193+
*/
194+
public function isRelationship(): bool
195+
{
196+
return $this->jsonApi()->route()->hasRelation();
197+
}
198+
199+
/**
200+
* Is this a request to not view a relationship?
201+
*
202+
* @return bool
203+
*/
204+
public function isNotRelationship(): bool
205+
{
206+
return !$this->isRelationship();
207+
}
208+
209+
/**
210+
* Get the field name for a relationship request.
211+
*
212+
* @return string|null
213+
*/
214+
public function getFieldName(): ?string
215+
{
216+
$route = $this->jsonApi()->route();
217+
218+
if ($route->hasRelation()) {
219+
return $route->fieldName();
220+
}
221+
222+
return null;
223+
}
224+
225+
/**
226+
* @return JsonApiService
227+
*/
228+
final protected function jsonApi(): JsonApiService
229+
{
230+
return $this->container->make(JsonApiService::class);
231+
}
232+
233+
/**
234+
* Is there a resource id?
235+
*
236+
* @return bool
237+
*/
238+
private function hasResourceId(): bool
239+
{
240+
return $this->jsonApi()->route()->hasResourceId();
241+
}
242+
243+
/**
244+
* Is the request not for a specific resource?
245+
*
246+
* @return bool
247+
*/
248+
private function doesntHaveResourceId(): bool
249+
{
250+
return !$this->hasResourceId();
251+
}
252+
253+
/**
254+
* Does the URL contain the keyword "relationships".
255+
*
256+
* @return bool
257+
*/
258+
private function urlHasRelationships(): bool
259+
{
260+
return Str::of($this->url())->contains('relationships');
261+
}
262+
}

src/ServiceProvider.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
use LaravelJsonApi\Contracts;
2828
use LaravelJsonApi\Core\Bus\Commands\Dispatcher as CommandDispatcher;
2929
use LaravelJsonApi\Core\Bus\Queries\Dispatcher as QueryDispatcher;
30+
use LaravelJsonApi\Core\Http\Actions\FetchMany;
3031
use LaravelJsonApi\Core\Http\Actions\FetchOne;
3132
use LaravelJsonApi\Core\Http\Actions\Store;
3233
use LaravelJsonApi\Core\JsonApiService;
@@ -158,6 +159,7 @@ private function bindServer(): void
158159
private function bindActionsCommandsAndQueries(): void
159160
{
160161
/** Actions */
162+
$this->app->bind(Contracts\Http\Actions\FetchMany::class, FetchMany::class);
161163
$this->app->bind(Contracts\Http\Actions\FetchOne::class, FetchOne::class);
162164
$this->app->bind(Contracts\Http\Actions\Store::class, Store::class);
163165

0 commit comments

Comments
 (0)
0