Skip to content

Commit 9c023cb

Browse files
committed
Merge branch 'master' into fix/rules-exploit
# Conflicts: # src/Rules/MutateRules.php # src/Rules/SearchRules.php
2 parents 8799b7b + 336d79b commit 9c023cb

File tree

15 files changed

+760
-10
lines changed

15 files changed

+760
-10
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,4 @@ Here is a quick look at what you can do using API search method:
9090

9191
- Metrics support
9292
- Refactor the response class
93-
- Alias for includes / aggregates
93+
- Alias for includes

src/Concerns/Resource/Paginable.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@ trait Paginable
1717
*/
1818
public function paginate($query, RestRequest $request)
1919
{
20+
$defaultLimit = $this->defaultLimit ?? 50;
21+
2022
// In case we have a scout builder
2123
if ($query instanceof Builder) {
22-
return $query->paginate($request->input('search.limit', 50), 'page', $request->input('search.page', 1));
24+
return $query->paginate($request->input('search.limit', $defaultLimit), 'page', $request->input('search.page', 1));
2325
}
2426

25-
return $query->paginate($request->input('search.limit', 50), ['*'], 'page', $request->input('search.page', 1));
27+
return $query->paginate($request->input('search.limit', $defaultLimit), ['*'], 'page', $request->input('search.page', 1));
2628
}
2729
}

src/Console/stubs/resource.stub

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ class {{ class }} extends RestResource
1313
*/
1414
public static $model = \{{ namespacedModel }}::class;
1515

16+
/**
17+
* The default value for the pagination limit.
18+
*
19+
* @var int
20+
*/
21+
public int $defaultLimit = 50;
22+
1623
/**
1724
* The exposed fields that could be provided
1825
* @param RestRequest $request

src/Console/stubs/user-resource.stub

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ class UserResource extends RestResource
1313
*/
1414
public static $model = \App\User::class;
1515

16+
/**
17+
* The default value for the pagination limit.
18+
*
19+
* @var int
20+
*/
21+
public int $defaultLimit = 50;
22+
1623
/**
1724
* The exposed fields that could be provided
1825
* @param RestRequest $request

src/Http/Resource.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ class Resource implements \JsonSerializable
4646
*/
4747
public static $response = Response::class;
4848

49+
/**
50+
* The default value for the pagination limit.
51+
*
52+
* @var int
53+
*/
54+
public int $defaultLimit = 50;
55+
4956
/**
5057
* Get a fresh instance of the model represented by the resource.
5158
*

src/Http/Response.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public function modelToResponse(Model $model, Resource $resource, array $request
7171
// Here we add the aggregates
7272
collect($currentRequestArray['aggregates'] ?? [])
7373
->map(function ($aggregate) {
74-
return Str::snake($aggregate['relation']).'_'.$aggregate['type'].(isset($aggregate['field']) ? '_'.$aggregate['field'] : '');
74+
return $aggregate['alias'] ?? Str::snake($aggregate['relation']).'_'.$aggregate['type'].(isset($aggregate['field']) ? '_'.$aggregate['field'] : '');
7575
})
7676
->toArray()
7777
)

src/Query/ScoutBuilder.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ public function search(array $parameters = [])
4949
$this->applyInstructions($parameters['instructions']);
5050
});
5151

52-
$this->queryBuilder->take($parameters['limit'] ?? 50);
52+
$defaultLimit = $this->resource->defaultLimit ?? 50;
53+
$this->queryBuilder->take($parameters['limit'] ?? $defaultLimit);
5354

5455
$this->queryBuilder
5556
->query(function (Builder $query) use ($parameters) {

src/Query/Traits/PerformSearch.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,13 @@ public function applyIncludes($includes)
237237
*/
238238
public function aggregate($aggregate)
239239
{
240-
return $this->queryBuilder->withAggregate([$aggregate['relation'] => function (Builder $query) use ($aggregate) {
240+
$relation = $aggregate['relation'];
241+
242+
if (isset($aggregate['alias'])) {
243+
$relation .= ' as '.$aggregate['alias'];
244+
}
245+
246+
return $this->queryBuilder->withAggregate([$relation => function (Builder $query) use ($aggregate) {
241247
$resource = $this->resource->relation($aggregate['relation'])?->resource();
242248

243249
$queryBuilder = $this->newQueryBuilder(['resource' => $resource, 'query' => $query]);

src/Relations/MorphedByMany.php

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,78 @@ public function afterMutating(Model $model, Relation $relation, array $mutationR
4747
{
4848
foreach ($mutationRelations[$relation->relation] as $mutationRelation) {
4949
if ($mutationRelation['operation'] === 'detach') {
50+
$toDetachModel = app()->make(QueryBuilder::class, ['resource' => $relation->resource()])
51+
->applyMutation($mutationRelation);
52+
53+
$this->resource()->authorizeToDetach($model, $toDetachModel);
54+
5055
$model
5156
->{$relation->relation}()
5257
->detach(
53-
app()->make(QueryBuilder::class, ['resource' => $relation->resource()])
54-
->applyMutation($mutationRelation)
55-
->getKey()
58+
$toDetachModel->getKey()
5659
);
57-
} else {
60+
} elseif ($mutationRelation['operation'] === 'attach') {
61+
$toAttachModel = app()->make(QueryBuilder::class, ['resource' => $relation->resource()])
62+
->applyMutation($mutationRelation);
63+
64+
$this->resource()->authorizeToAttach($model, $toAttachModel);
65+
5866
$model
5967
->{$relation->relation}()
6068
->attach(
69+
[
70+
$toAttachModel->getKey() => $mutationRelation['pivot'] ?? [],
71+
]
72+
);
73+
} elseif ($mutationRelation['operation'] === 'toggle') {
74+
$results = $model
75+
->{$relation->relation}()
76+
->toggle(
77+
[
78+
app()->make(QueryBuilder::class, ['resource' => $relation->resource()])
79+
->applyMutation($mutationRelation)
80+
->getKey() => $mutationRelation['pivot'] ?? [],
81+
]
82+
);
83+
84+
foreach ($results['attached'] as $attached) {
85+
$this->resource()->authorizeToAttach($model, $relation->resource()::$model::find($attached));
86+
}
87+
88+
foreach ($results['detached'] as $detached) {
89+
$this->resource()->authorizeToDetach($model, $relation->resource()::$model::find($detached));
90+
}
91+
} elseif ($mutationRelation['operation'] === 'sync') {
92+
$results = $model
93+
->{$relation->relation}()
94+
->sync(
6195
[
6296
app()->make(QueryBuilder::class, ['resource' => $relation->resource()])
6397
->applyMutation($mutationRelation)
6498
->getKey() => $mutationRelation['pivot'] ?? [],
99+
],
100+
!isset($mutationRelation['without_detaching']) || !$mutationRelation['without_detaching']
101+
);
102+
103+
foreach ($results['attached'] as $attached) {
104+
$this->resource()->authorizeToAttach($model, $relation->resource()::$model::find($attached));
105+
}
106+
107+
foreach ($results['detached'] as $detached) {
108+
$this->resource()->authorizeToDetach($model, $relation->resource()::$model::find($detached));
109+
}
110+
} elseif (in_array($mutationRelation['operation'], ['create', 'update'])) {
111+
$toAttachModel = app()->make(QueryBuilder::class, ['resource' => $relation->resource()])
112+
->applyMutation($mutationRelation);
113+
114+
$this->resource()->authorizeToAttach($model, $toAttachModel);
115+
116+
$model
117+
->{$relation->relation}()
118+
->syncWithoutDetaching(
119+
[
120+
$toAttachModel
121+
->getKey() => $mutationRelation['pivot'] ?? [],
65122
]
66123
);
67124
}

0 commit comments

Comments
 (0)