Skip to content

Commit c6e209f

Browse files
authored
Merge pull request #8 from Lomkit/morph-relationships
Morph relationships
2 parents 0c231b6 + e1516ff commit c6e209f

File tree

67 files changed

+5018
-78
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+5018
-78
lines changed

README.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,10 @@ TODO
7676

7777
TODO
7878

79-
## Roadmap
79+
## Roadmap for the end of bêta (Estimated delivery October 2023)
8080

81-
- Morph support
82-
- Through relation support
8381
- Custom directives (Filters / sorting)
8482
- Actions / Metrics
85-
- Automatic Gates
83+
- Automatic Gates (with config customisation)
8684
- Aggregating
8785
- Automatic documentation with extension possible

src/Concerns/PerformsRestOperations.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ public function destroy(DestroyRequest $request) {
6060
$resource->performDelete($request, $model);
6161
}
6262

63-
//@TODO: il faut prévoir de pouvoir load des relations ici ?
6463
return $resource::newResponse()
6564
->resource($resource)
6665
->responsable($models);

src/Concerns/Relations/HasPivotFields.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
trait HasPivotFields
66
{
77
protected array $pivotFields = [];
8+
protected array $pivotRules = [];
89

910
public function getPivotFields() {
1011
return $this->pivotFields;
@@ -15,4 +16,18 @@ public function withPivotFields(array $pivotFields) {
1516
$this->pivotFields = $pivotFields;
1617
});
1718
}
19+
20+
public function withPivotRules(array $pivotRules) {
21+
return tap($this, function () use ($pivotRules) {
22+
$this->pivotRules = $pivotRules;
23+
});
24+
}
25+
26+
/**
27+
* @return array
28+
*/
29+
public function getPivotRules(): array
30+
{
31+
return $this->pivotRules;
32+
}
1833
}

src/Concerns/Resource/Relationable.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ public function relation($name) {
1919
return $relation->relation === $relationName;
2020
});
2121

22-
//TODO: be careful here, nested morph relation here are not supported, might need to protect params validator
2322
if ($isSubRelation && Str::contains($nestedRelation = Str::after($name, '.'), '.')) {
2423
return $relation->resource()->relation($nestedRelation);
2524
}

src/Concerns/Resource/Rulable.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99

1010
trait Rulable
1111
{
12+
public function rules(RestRequest $request) {
13+
return [];
14+
}
15+
1216
public function createRules(RestRequest $request) {
1317
return [];
1418
}

src/Http/Requests/MutateRequest.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
use Lomkit\Rest\Relations\BelongsToMany;
1414
use Lomkit\Rest\Relations\HasMany;
1515
use Lomkit\Rest\Relations\HasManyThrough;
16+
use Lomkit\Rest\Relations\MorphedByMany;
17+
use Lomkit\Rest\Relations\MorphMany;
18+
use Lomkit\Rest\Relations\MorphToMany;
1619
use Lomkit\Rest\Rules\CustomRulable;
1720
use Lomkit\Rest\Rules\Includable;
1821
use Lomkit\Rest\Rules\RequiredRelation;
@@ -70,15 +73,13 @@ protected function relationRules(Resource $resource, string $prefix = '', $loade
7073
) {
7174
$prefixRelation = $prefix.'.'.$relation->relation;
7275

73-
if ($relation instanceof BelongsToMany || $relation instanceof HasMany || $relation instanceof HasManyThrough) {
76+
if ($relation->hasMultipleEntries()) {
7477
$prefixRelation .= '.*';
7578
}
7679

7780
$rules = array_merge_recursive(
7881
$rules,
79-
[
80-
$prefix.'.'.$relation->relation => $relation->rules($resource)
81-
],
82+
$relation->rules($resource, $prefix.'.'.$relation->relation),
8283
$this->mutateRules($relation->resource(), $prefixRelation, array_merge($loadedRelations, [$relation->relation]))
8384
);
8485
}

src/Query/Traits/PerformSearch.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public function sort($field, $direction = 'asc') {
8585

8686
public function applySorts($sorts) {
8787
foreach ($sorts as $sort) {
88-
$this->sort($sort['field'], $sort['direction'] ?? 'asc');
88+
$this->sort($this->queryBuilder->getModel()->getTable().'.'.$sort['field'], $sort['direction'] ?? 'asc');
8989
}
9090
}
9191

src/Relations/BelongsToMany.php

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,55 @@
55
use Closure;
66
use Illuminate\Database\Eloquent\Builder;
77
use Illuminate\Database\Eloquent\Model;
8+
use Illuminate\Support\Arr;
9+
use Illuminate\Validation\Rule;
810
use Lomkit\Rest\Concerns\Relations\HasPivotFields;
911
use Lomkit\Rest\Contracts\QueryBuilder;
1012
use Lomkit\Rest\Contracts\RelationResource;
13+
use Lomkit\Rest\Http\Resource;
14+
use Lomkit\Rest\Relations\Traits\HasMultipleResults;
1115

1216
class BelongsToMany extends Relation implements RelationResource
1317
{
14-
use HasPivotFields;
18+
use HasPivotFields, HasMultipleResults;
19+
20+
public function rules(Resource $resource, string $prefix)
21+
{
22+
return array_merge(
23+
parent::rules($resource, $prefix),
24+
[
25+
$prefix.'.*.pivot' => [
26+
'prohibited_if:'.$prefix.'.*.operation,detach',
27+
'array:'.Arr::join($this->getPivotFields(), ',')
28+
]
29+
]
30+
);
31+
}
1532

1633
public function afterMutating(Model $model, Relation $relation, array $mutationRelations)
1734
{
1835
foreach ($mutationRelations[$relation->relation] as $mutationRelation) {
19-
$model
20-
->{$relation->relation}()
21-
->{$mutationRelation['operation'] === 'detach' ? 'detach' : 'attach'}(
22-
app()->make(QueryBuilder::class, ['resource' => $relation->resource()])
23-
->applyMutation($mutationRelation)
24-
);
36+
if ($mutationRelation['operation'] === 'detach') {
37+
$model
38+
->{$relation->relation}()
39+
->detach(
40+
app()->make(QueryBuilder::class, ['resource' => $relation->resource()])
41+
->applyMutation($mutationRelation)
42+
->getKey()
43+
);
44+
} else {
45+
$model
46+
->{$relation->relation}()
47+
->attach(
48+
[
49+
app()->make(QueryBuilder::class, ['resource' => $relation->resource()])
50+
->applyMutation($mutationRelation)
51+
->getKey()
52+
=>
53+
$mutationRelation['pivot'] ?? []
54+
]
55+
);
56+
}
2557
}
2658
}
2759
}

src/Relations/HasMany.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77
use Illuminate\Database\Eloquent\Model;
88
use Lomkit\Rest\Contracts\QueryBuilder;
99
use Lomkit\Rest\Contracts\RelationResource;
10+
use Lomkit\Rest\Relations\Traits\HasMultipleResults;
1011

1112
class HasMany extends Relation implements RelationResource
1213
{
14+
use HasMultipleResults;
15+
1316
public function afterMutating(Model $model, Relation $relation, array $mutationRelations)
1417
{
1518
foreach ($mutationRelations[$relation->relation] as $mutationRelation) {

src/Relations/HasManyThrough.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,21 @@
88
use Lomkit\Rest\Contracts\QueryBuilder;
99
use Lomkit\Rest\Contracts\RelationResource;
1010
use Lomkit\Rest\Http\Resource;
11+
use Lomkit\Rest\Relations\Traits\HasMultipleResults;
1112

1213
class HasManyThrough extends Relation implements RelationResource
1314
{
15+
use HasMultipleResults;
16+
1417
public function afterMutating(Model $model, Relation $relation, array $mutationRelations)
1518
{
1619
throw new \RuntimeException('You can\'t mutate a \'HasManyThrough\' relation.');
1720
}
1821

19-
public function rules(Resource $resource)
22+
public function rules(Resource $resource, string $prefix)
2023
{
2124
return [
22-
'prohibited'
25+
$prefix => 'prohibited'
2326
];
2427
}
2528
}

0 commit comments

Comments
 (0)