Skip to content

Commit e2a73c6

Browse files
authored
Do not display eager fields on index requests. (#293)
* Do not display eager fields on index requests. * Apply fixes from StyleCI (#294) * Fix unit tests. * wip * wip
1 parent 9b65393 commit e2a73c6

File tree

15 files changed

+144
-88
lines changed

15 files changed

+144
-88
lines changed

UPGRADING.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,18 @@ Because there are many breaking changes an upgrade is not that easy. There are m
55
## From v3 to v4
66

77
- Dropped support for laravel passport
8+
- Now you have to explicitly define the `allowRestify` method in the model policy, by default Restify don't allow you to use repositories.
9+
- `viewAny` policy is not used anymore, you can delete it.
810
- The default exception handler is the Laravel one, see `restify.php -> handler`
911
- `fillCallback` signature has changed
1012
- By default it will do not allow you to attach `belongsToMany` and `morphToMany` relationships. You will have to add `BelongsToMany` or `MorphToMany` field into your repository
13+
- All of the `Repository` getter methods should declare the returned type, for instance the `fieldsForIndex` method should say that it returns an `:array`
14+
- Attach endpoint:
15+
```php
16+
"api/restify/users/{$user->id}/attach/roles", [
17+
'roles' => [$role->id],
18+
]
19+
```
20+
now requires to have a `Binaryk\LaravelRestify\Fields\BelongsToMany` or `Binaryk\LaravelRestify\Fields\MorphToMany` field to be defined in the repository.
1121

22+
- Field method `append` renamed to `value`.

docs/docs/4.0/repository-pattern/field.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,18 +158,18 @@ Field::new('password')->showRequest(function ($value) {
158158
});
159159
```
160160

161-
## Append Callback
161+
## Value Callback
162162

163-
Usually, there is necessary to store a field as `Auth::id()`. This field will be automatically populated by Restify if you specify the `append` value for it:
163+
Usually, there is necessary to store a field as `Auth::id()`. This field will be automatically populated by Restify if you specify the `value` value for it:
164164

165165
```php
166-
Field::new('user_id')->append(Auth::id());
166+
Field::new('user_id')->value(Auth::id());
167167
```
168168

169169
or using a closure:
170170

171171
```php
172-
Field::new('user_id')->hidden()->append(function(RestifyRequest $request, $model, $attribute) {
172+
Field::new('user_id')->hidden()->value(function(RestifyRequest $request, $model, $attribute) {
173173
return $request->user()->id;
174174
});
175175
```
@@ -190,10 +190,10 @@ Field can be setup as hidden:
190190
Field::new('token')->hidden(); // this will not be visible
191191
```
192192

193-
However, you can populate the field value when the entity is stored, by using `append`:
193+
However, you can populate the field value when the entity is stored, by using `value`:
194194

195195
```php
196-
Field::new('token')->append(Str::random(32))->hidden();
196+
Field::new('token')->value(Str::random(32))->hidden();
197197
```
198198

199199
# Variations

src/Fields/Field.php

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ class Field extends OrganicField implements JsonSerializable
106106
*
107107
* @var callable
108108
*/
109-
protected $appendCallback;
109+
protected $valueCallback;
110110

111111
/**
112112
* Closure be used to be called after the field value stored.
@@ -217,7 +217,7 @@ public function fillAttribute(RestifyRequest $request, $model, int $bulkRow = nu
217217
}
218218

219219
if ($this->isHidden($request)) {
220-
return $this->fillAttributeFromAppend(
220+
return $this->fillAttributeFromValue(
221221
$request, $model, $this->label ?? $this->attribute
222222
);
223223
}
@@ -226,7 +226,11 @@ public function fillAttribute(RestifyRequest $request, $model, int $bulkRow = nu
226226
$request, $model, $this->label ?? $this->attribute, $bulkRow
227227
);
228228

229-
$this->fillAttributeFromAppend(
229+
$this->fillAttributeFromCallback(
230+
$request, $model, $this->label ?? $this->attribute, $bulkRow
231+
);
232+
233+
$this->fillAttributeFromValue(
230234
$request, $model, $this->label ?? $this->attribute, $bulkRow
231235
);
232236

@@ -247,29 +251,48 @@ protected function fillAttributeFromRequest(RestifyRequest $request, $model, $at
247251
? $attribute
248252
: "{$bulkRow}.{$attribute}";
249253

250-
tap(($request->input($attribute) ?? $request[$attribute]), fn ($value) => $model->{$this->attribute} = is_callable($cb = $this->guessFillableMethod($request))
251-
? call_user_func($cb, $value, $request, $model, $attribute, $bulkRow)
252-
: ($request->has($attribute) ? $value : $model->{$this->attribute})
254+
if (! ($request->exists($attribute) || $request->input($attribute))) {
255+
return;
256+
}
257+
258+
tap(($request->input($attribute) ?? $request[$attribute]), fn ($value) => $model->{$this->attribute} = $request->has($attribute)
259+
? $value
260+
: $model->{$this->attribute}
253261
);
254262
}
255263

256264
/**
257-
* Fill the model with the value from append.
265+
* Fill the model with value from the callback.
266+
*
267+
* @param RestifyRequest $request
268+
* @param $model
269+
* @param $attribute
270+
* @param int|null $bulkRow
271+
*/
272+
protected function fillAttributeFromCallback(RestifyRequest $request, $model, $attribute, int $bulkRow = null)
273+
{
274+
if (is_callable($cb = $this->guessFillableMethod($request))) {
275+
$model->{$this->attribute} = call_user_func($cb, $request, $model, $attribute, $bulkRow);
276+
}
277+
}
278+
279+
/**
280+
* Fill the model with the value from value.
258281
*
259282
* @param RestifyRequest $request
260283
* @param $model
261284
* @param $attribute
262285
* @return Field
263286
*/
264-
protected function fillAttributeFromAppend(RestifyRequest $request, $model, $attribute)
287+
protected function fillAttributeFromValue(RestifyRequest $request, $model, $attribute)
265288
{
266-
if (! isset($this->appendCallback)) {
289+
if (! isset($this->valueCallback)) {
267290
return;
268291
}
269292

270-
$model->{$attribute} = is_callable($this->appendCallback)
271-
? call_user_func($this->appendCallback, $request, $model, $attribute)
272-
: $this->appendCallback;
293+
$model->{$attribute} = is_callable($this->valueCallback)
294+
? call_user_func($this->valueCallback, $request, $model, $attribute)
295+
: $this->valueCallback;
273296

274297
return $this;
275298
}
@@ -568,18 +591,28 @@ public function hidden($callback = true)
568591
}
569592

570593
/**
571-
* Append values when store/update.
594+
* Force set values when store/update.
572595
*
573596
* @param callable|string $value
574597
* @return $this
575598
*/
576-
public function append($value)
599+
public function value($value)
577600
{
578-
$this->appendCallback = $value;
601+
$this->valueCallback = $value;
579602

580603
return $this;
581604
}
582605

606+
/**
607+
* @param $value
608+
* @return $this
609+
* @deprecated
610+
*/
611+
public function append($value)
612+
{
613+
return $this->value($value);
614+
}
615+
583616
public function setRepository(Repository $repository): Field
584617
{
585618
$this->repository = $repository;

src/Repositories/Concerns/InteractsWithAttachers.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public function authorizeBelongsToMany(RestifyRequest $request): self
2020
{
2121
if (is_null($field = $this->belongsToManyField($request))) {
2222
$class = class_basename($request->repository());
23-
abort(400, "Missing BelongsToMany or MorphToMany field for [{$request->relatedRepository}]. This field should be in the [{$class}] class.");
23+
abort(400, "Missing BelongsToMany or MorphToMany field for [{$request->relatedRepository}]. This field should be in the [{$class}] class. Or you are not authorized to use that repository (see `allowRestify` policy method).");
2424
}
2525

2626
$field->authorizeToAttach(

src/Repositories/Repository.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Binaryk\LaravelRestify\Fields\Field;
1111
use Binaryk\LaravelRestify\Fields\FieldCollection;
1212
use Binaryk\LaravelRestify\Filter;
13+
use Binaryk\LaravelRestify\Http\Requests\RepositoryShowRequest;
1314
use Binaryk\LaravelRestify\Http\Requests\RepositoryStoreBulkRequest;
1415
use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
1516
use Binaryk\LaravelRestify\Models\CreationAware;
@@ -511,9 +512,10 @@ public function resolveRelationships($request): array
511512
$withs = collect();
512513

513514
/** * To avoid circular relationships and deep stack calls, we will do not load eager fields. */
514-
if (! $this->isEagerState()) {
515+
if (! $this->isEagerState() && $request instanceof RepositoryShowRequest) {
515516
$this->collectFields($request)
516517
->forEager($request, $this)
518+
->filter(fn (EagerField $field) => $field->isShownOnShow($request, $this))
517519
->each(fn (EagerField $field) => $withs->put($field->attribute, $field->resolve($this)->value));
518520
}
519521

tests/Controllers/ProfileControllerTest.php

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ protected function setUp(): void
2727
public function test_profile_returns_authenticated_user()
2828
{
2929
$response = $this->getJson('profile')
30-
->assertStatus(200)
30+
->assertOk()
3131
->assertJsonStructure([
3232
'data',
3333
]);
@@ -40,7 +40,7 @@ public function test_profile_returns_authenticated_user()
4040
public function test_profile_returns_authenticated_user_with_related_posts()
4141
{
4242
$this->getJson('profile?related=posts')
43-
->assertStatus(200)
43+
->assertOk()
4444
->assertJsonStructure([
4545
'data' => [
4646
'posts' => [
@@ -55,7 +55,7 @@ public function test_profile_returns_authenticated_user_with_related_posts()
5555
public function test_profile_returns_authenticated_user_with_meta_profile_data()
5656
{
5757
$this->getJson('profile')
58-
->assertStatus(200)
58+
->assertOk()
5959
->assertJsonStructure([
6060
'data',
6161
'meta' => [
@@ -69,8 +69,7 @@ public function test_profile_update()
6969
$response = $this->putJson('profile', [
7070
'email' => '[email protected]',
7171
'name' => 'Eduard',
72-
])
73-
->assertStatus(200);
72+
])->assertOk();
7473

7574
$response->assertJsonFragment([
7675
'email' => '[email protected]',
@@ -85,8 +84,7 @@ public function test_profile_update_password()
8584
'name' => 'Eduard',
8685
'password' => 'secret',
8786
'password_confirmation' => 'secret',
88-
])
89-
->assertStatus(200);
87+
])->assertOk();
9088

9189
$this->assertTrue(Hash::check('secret', $this->authenticatedAs->password));
9290
}
@@ -100,8 +98,7 @@ public function test_profile_update_unique_email()
10098
$this->putJson('profile', [
10199
'email' => '[email protected]',
102100
'name' => 'Eduard',
103-
])
104-
->assertStatus(400);
101+
])->assertStatus(400);
105102
}
106103

107104
public function test_profile_upload_avatar()
@@ -110,8 +107,7 @@ public function test_profile_upload_avatar()
110107

111108
$this->postJson('profile/avatar', [
112109
'avatar' => $file,
113-
])
114-
->assertStatus(200);
110+
])->assertOk();
115111
}
116112

117113
public function test_profile_validation_from_repository()
@@ -153,7 +149,7 @@ public function test_profile_returns_authenticated_user_with_related_posts_via_r
153149
UserRepository::$canUseForProfile = true;
154150

155151
$response = $this->getJson('profile?related=posts')
156-
->assertStatus(200)
152+
->assertOk()
157153
->assertJsonStructure([
158154
'attributes',
159155
'relationships' => [
@@ -179,7 +175,7 @@ public function test_profile_returns_authenticated_user_with_meta_profile_data_v
179175
];
180176

181177
$this->getJson('profile')
182-
->assertStatus(200)
178+
->assertOk()
183179
->assertJsonStructure([
184180
'attributes',
185181
'meta' => [
@@ -195,8 +191,7 @@ public function test_profile_update_via_repository()
195191
$response = $this->putJson('profile', [
196192
'email' => '[email protected]',
197193
'name' => 'Eduard',
198-
])
199-
->assertStatus(200);
194+
])->assertOk();
200195

201196
$response->assertJsonFragment([
202197
'email' => '[email protected]',

tests/Controllers/RepositoryStoreControllerTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Binaryk\LaravelRestify\Tests\Fixtures\Post\Post;
66
use Binaryk\LaravelRestify\Tests\Fixtures\Post\PostPolicy;
7+
use Binaryk\LaravelRestify\Tests\Fixtures\Post\PostUnauthorizedFieldRepository;
78
use Binaryk\LaravelRestify\Tests\IntegrationTest;
89
use Illuminate\Support\Facades\Gate;
910

@@ -94,7 +95,7 @@ public function test_will_not_store_unauthorized_fields()
9495
public function test_will_not_store_readonly_fields()
9596
{
9697
$user = $this->mockUsers()->first();
97-
$response = $this->postJson('posts-unauthorized-fields', [
98+
$response = $this->postJson(PostUnauthorizedFieldRepository::uriKey(), [
9899
'user_id' => $user->id,
99100
'image' => 'avatar.png',
100101
'title' => 'Some post title',

tests/Fields/BelongsToFieldTest.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,15 @@ protected function tearDown(): void
3838

3939
public function test_present_on_relations()
4040
{
41-
factory(Post::class)->create([
41+
$post = factory(Post::class)->create([
4242
'user_id' => factory(User::class),
4343
]);
4444

45-
$this->get(PostWithUserRepository::uriKey())
45+
$this->get(PostWithUserRepository::uriKey()."/$post->id")
4646
->assertJsonStructure([
4747
'data' => [
48-
[
49-
'relationships' => [
50-
'user',
51-
],
48+
'relationships' => [
49+
'user',
5250
],
5351
],
5452
]);

0 commit comments

Comments
 (0)