1 | <?php |
||
2 | |||
3 | declare(strict_types=1); |
||
4 | |||
5 | namespace Cycle\ORM\Relation; |
||
6 | |||
7 | use Cycle\ORM\ORMInterface; |
||
8 | use Cycle\ORM\Reference\ReferenceInterface; |
||
9 | use Cycle\ORM\Relation\Traits\HasSomeTrait; |
||
10 | use Cycle\ORM\Relation\Traits\ToOneTrait; |
||
11 | use Cycle\ORM\Service\EntityProviderInterface; |
||
12 | use Cycle\ORM\Transaction\Pool; |
||
13 | use Cycle\ORM\Transaction\Tuple; |
||
14 | |||
15 | /** |
||
16 | * Provides the ability to own and forward context values to child entity. |
||
17 | * |
||
18 | * @internal |
||
19 | */ |
||
20 | class HasOne extends AbstractRelation |
||
21 | { |
||
22 | use HasSomeTrait; |
||
0 ignored issues
–
show
introduced
by
![]() |
|||
23 | use ToOneTrait; |
||
24 | |||
25 | 1152 | public function __construct(ORMInterface $orm, string $role, string $name, string $target, array $schema) |
|
26 | { |
||
27 | 1152 | $this->entityProvider = $orm->getService(EntityProviderInterface::class); |
|
28 | |||
29 | 1152 | parent::__construct($orm, $role, $name, $target, $schema); |
|
30 | } |
||
31 | |||
32 | 580 | public function prepare(Pool $pool, Tuple $tuple, mixed $related, bool $load = true): void |
|
33 | { |
||
34 | 580 | $node = $tuple->node; |
|
35 | 580 | $original = $node->getRelation($this->getName()); |
|
36 | 580 | $tuple->state->setRelation($this->getName(), $related); |
|
37 | |||
38 | 580 | if ($original instanceof ReferenceInterface) { |
|
39 | 288 | if (!$load && $this->compareReferences($original, $related)) { |
|
40 | 208 | $original = $related instanceof ReferenceInterface ? $this->resolve($related, false) : $related; |
|
41 | 208 | if ($original === null) { |
|
42 | // not found in heap |
||
43 | 200 | $node->setRelation($this->getName(), $related); |
|
44 | 200 | $tuple->state->setRelationStatus($this->getName(), RelationInterface::STATUS_RESOLVED); |
|
45 | 208 | return; |
|
46 | } |
||
47 | } else { |
||
48 | 136 | $original = $this->resolve($original, true); |
|
49 | } |
||
50 | 136 | $node->setRelation($this->getName(), $original); |
|
51 | } |
||
52 | |||
53 | 540 | if ($related instanceof ReferenceInterface) { |
|
54 | 24 | $related = $this->resolve($related, true); |
|
55 | 24 | $tuple->state->setRelation($this->getName(), $related); |
|
56 | } elseif (SpecialValue::isNotSet($related)) { |
||
57 | $tuple->state->setRelationStatus($this->getName(), RelationInterface::STATUS_RESOLVED); |
||
58 | 540 | return; |
|
59 | 276 | } |
|
60 | 276 | ||
61 | 204 | if ($related === null) { |
|
62 | $tuple->state->setRelationStatus($this->getName(), RelationInterface::STATUS_RESOLVED); |
||
63 | 104 | if ($original === null) { |
|
64 | 104 | return; |
|
65 | } |
||
66 | 464 | $this->deleteChild($pool, $tuple, $original); |
|
67 | return; |
||
68 | 464 | } |
|
69 | 464 | $tuple->state->setRelationStatus($this->getName(), RelationInterface::STATUS_PROCESS); |
|
70 | |||
71 | 464 | $rTuple = $pool->attachStore($related, true); |
|
72 | 160 | $this->assertValid($rTuple->node); |
|
73 | |||
74 | if ($original !== null && $original !== $related) { |
||
75 | $this->deleteChild($pool, $tuple, $original); |
||
76 | 464 | } |
|
77 | } |
||
78 | 464 | ||
79 | public function queue(Pool $pool, Tuple $tuple): void |
||
80 | { |
||
81 | 464 | if ($tuple->task !== Tuple::TASK_STORE) { |
|
82 | 464 | return; |
|
83 | } |
||
84 | 464 | $related = $tuple->state->getRelation($this->getName()); |
|
85 | $tuple->state->setRelationStatus($this->getName(), RelationInterface::STATUS_RESOLVED); |
||
86 | |||
87 | if ($related instanceof ReferenceInterface && !$related->hasValue()) { |
||
88 | 464 | return; |
|
89 | 464 | } |
|
90 | 464 | ||
91 | $rTuple = $pool->offsetGet($related); |
||
92 | $this->applyChanges($tuple, $rTuple); |
||
93 | $rTuple->state->setRelationStatus($this->getTargetRelationName(), RelationInterface::STATUS_RESOLVED); |
||
94 | } |
||
95 | } |
||
96 |