-
-
Notifications
You must be signed in to change notification settings - Fork 468
Expand file tree
/
Copy pathSaveModel.php
More file actions
114 lines (93 loc) · 3.99 KB
/
Copy pathSaveModel.php
File metadata and controls
114 lines (93 loc) · 3.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<?php declare(strict_types=1);
namespace Nuwave\Lighthouse\Execution\Arguments;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasOneOrMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\Relation;
use Nuwave\Lighthouse\Support\Contracts\ArgResolver;
use Nuwave\Lighthouse\Support\Contracts\PreSaveArgumentsAware;
use Nuwave\Lighthouse\Support\Contracts\SaveAwareArgResolver;
class SaveModel implements ArgResolver, PreSaveArgumentsAware
{
/** @var list<\Nuwave\Lighthouse\Execution\Arguments\Argument> */
protected array $preSaveArguments = [];
public function __construct(
/** @var \Illuminate\Database\Eloquent\Relations\Relation<\Illuminate\Database\Eloquent\Model>|null $parentRelation */
protected ?Relation $parentRelation = null,
) {}
public function withPreSaveArguments(array $arguments): static
{
$clone = clone $this;
$clone->preSaveArguments = $arguments;
return $clone;
}
/**
* @param Model $model
* @param ArgumentSet $args
*/
public function __invoke($model, $args): Model
{
[$preSave, $remaining] = ArgPartitioner::preSaveNestedArgResolvers($args, $model);
// Extract $morphTo first, as MorphTo extends BelongsTo
[$morphTo, $remaining] = ArgPartitioner::relationMethods(
$remaining,
$model,
MorphTo::class,
);
[$belongsTo, $remaining] = ArgPartitioner::relationMethods(
$remaining,
$model,
BelongsTo::class,
);
$argsToFill = $remaining->toArray();
// Use all the remaining attributes and fill the model
if (config('lighthouse.force_fill')) {
$model->forceFill($argsToFill);
} else {
$model->fill($argsToFill);
}
foreach ($belongsTo->arguments as $relationName => $nestedOperations) {
$belongsTo = $model->{$relationName}();
assert($belongsTo instanceof BelongsTo);
$belongsToResolver = new ResolveNested(new NestedBelongsTo($belongsTo));
$belongsToResolver($model, $nestedOperations->value);
}
foreach ($morphTo->arguments as $relationName => $nestedOperations) {
$morphTo = $model->{$relationName}();
assert($morphTo instanceof MorphTo);
$morphToResolver = new ResolveNested(new NestedMorphTo($morphTo));
$morphToResolver($model, $nestedOperations->value);
}
foreach ([
...array_values($preSave->arguments),
...$this->preSaveArguments,
] as $preSaveArgument) {
$resolver = $preSaveArgument->resolver;
assert($resolver instanceof SaveAwareArgResolver, 'Resolver must be a SaveAwareArgResolver because we partitioned for it.');
$resolver($model, $preSaveArgument->value);
}
if ($this->parentRelation instanceof HasOneOrMany) {
// If we are already resolving a nested create, we might
// already have an instance of the parent relation available.
// In that case, use it to set the current model as a child.
$this->parentRelation->save($model);
return $model;
}
$model->save();
if ($this->parentRelation instanceof BelongsTo) {
$childModel = $this->parentRelation->associate($model);
// If the child Model does not exist (still to be saved),
// a save could break any pending belongsTo relations that still
// need to be created and associated with it.
if ($childModel->exists) {
$childModel->save();
}
}
if ($this->parentRelation instanceof BelongsToMany) {
$this->parentRelation->syncWithoutDetaching($model);
}
return $model;
}
}