Completed
Push — 2.x ( 0b6590...78009d )
by Aleksei
20s queued 15s
created

RefersTo::queue()   D

Complexity

Conditions 18
Paths 41

Size

Total Lines 61
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 30
CRAP Score 19.5009

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 18
eloc 42
c 1
b 0
f 0
nc 41
nop 2
dl 0
loc 61
ccs 30
cts 36
cp 0.8333
crap 19.5009
rs 4.8666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cycle\ORM\Relation;
6
7
use Cycle\ORM\Heap\Node;
8
use Cycle\ORM\Heap\State;
9
use Cycle\ORM\ORMInterface;
10
use Cycle\ORM\Reference\ReferenceInterface;
11
use Cycle\ORM\Relation\Traits\ToOneTrait;
12
use Cycle\ORM\Service\EntityProviderInterface;
13
use Cycle\ORM\Transaction\Pool;
14
use Cycle\ORM\Transaction\Tuple;
15
16
/**
17
 * Variation of belongs-to relation which provides the ability to be self linked. Relation can be used
18
 * to create cyclic references. Relation does not trigger store operation of referenced object!
19
 *
20
 * @internal
21
 */
22
class RefersTo extends AbstractRelation implements DependencyInterface
23
{
24
    use ToOneTrait;
25
26 870
    public function __construct(ORMInterface $orm, string $role, string $name, string $target, array $schema)
27
    {
28 870
        $this->entityProvider = $orm->getService(EntityProviderInterface::class);
29
30 870
        parent::__construct($orm, $role, $name, $target, $schema);
31
    }
32
33 406
    public function prepare(Pool $pool, Tuple $tuple, mixed $related, bool $load = true): void
34
    {
35 406
        $state = $tuple->state;
36 406
        $relName = $this->getName();
37
38 406
        if (SpecialValue::isNotSet($related)) {
39 8
            if (!$state->hasRelation($relName)) {
40 8
                $state->setRelationStatus($relName, RelationInterface::STATUS_DEFERRED);
41
                return;
42 406
            }
43 142
44
            $related = $state->getRelation($relName);
45 376
        }
46 376
47 96
        $node = $tuple->node;
48 96
        $tuple->state->setRelation($relName, $related);
49
50
        if ($related instanceof ReferenceInterface && $this->resolve($related, false) !== null) {
51 352
            $related = $related->getValue();
52 352
            $tuple->state->setRelation($relName, $related);
53 352
        }
54 320
        if ($this->checkNullValue($node, $tuple->state, $related)) {
55
            return;
56
        }
57
        $this->registerWaitingFields($tuple->state, false);
58 424
        if ($related instanceof ReferenceInterface) {
59
            $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_DEFERRED);
60 424
            return;
61 424
        }
62
63 424
        $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_PROCESS);
64 8
        $rTuple = $pool->offsetGet($related);
65 8
        if ($rTuple === null && $this->isCascade()) {
66
            $pool->attachStore($related, false, null, null, false);
67 424
        }
68 88
    }
69 88
70 88
    public function queue(Pool $pool, Tuple $tuple): void
71 88
    {
72
        $state = $tuple->state;
73 88
        $relName = $this->getName();
74 88
75 88
        if (!$state->hasRelation($relName)) {
76
            $state->setRelationStatus($relName, RelationInterface::STATUS_RESOLVED);
77
            return;
78 408
        }
79 56
80
        $node = $tuple->node;
81 352
        $related = $tuple->state->getRelation($relName);
82 352
83
        if ($related instanceof ReferenceInterface && ($related->hasValue() || $this->resolve($related, false) !== null)) {
84
            $related = $related->getValue();
85
            $tuple->state->setRelation($relName, $related);
86
        }
87
        if ($related instanceof ReferenceInterface) {
88
            $scope = $related->getScope();
89
            if (\array_intersect($this->outerKeys, \array_keys($scope))) {
90
                foreach ($this->outerKeys as $i => $outerKey) {
91
                    $tuple->state->register($this->innerKeys[$i], $scope[$outerKey]);
92
                }
93
                $node->setRelation($relName, $related);
94
                $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_RESOLVED);
95 352
                return;
96 208
            }
97 208
        }
98 352
        if ($this->checkNullValue($tuple->node, $tuple->state, $related)) {
99
            return;
100 328
        }
101 328
        $rTuple = $pool->offsetGet($related);
102 328
        if ($rTuple === null) {
103 328
            if ($this->isCascade()) {
104
                // todo: cascade true?
105
                $rTuple = $pool->attachStore($related, false, null, null, false);
106 192
            } elseif (
107 192
                $tuple->state->getRelationStatus($relName) !== RelationInterface::STATUS_DEFERRED
108
                || $tuple->status !== Tuple::STATUS_PROPOSED
109
            ) {
110
                $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_DEFERRED);
111 328
                return;
112
            } else {
113 328
                $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_RESOLVED);
114 328
                return;
115 328
            }
116 328
        }
117
118
        if ($rTuple->status === Tuple::STATUS_PROCESSED
119
            || ($rTuple->status > Tuple::STATUS_PREPARING
120
                && $rTuple->state->getStatus() !== node::NEW
121 454
                && \array_intersect($this->outerKeys, $rTuple->state->getWaitingFields()) === [])
122
        ) {
123 454
            $this->pullValues($tuple->state, $rTuple->state);
124 376
            $node->setRelation($relName, $related);
125
            $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_RESOLVED);
126 198
            return;
127
        }
128 198
129
        if ($tuple->status !== Tuple::STATUS_PREPARING) {
130 96
            $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_DEFERRED);
131 96
        }
132
    }
133
134
    private function pullValues(State $state, State $rState): void
135 198
    {
136 198
        $changes = $rState->getTransactionData();
137 198
        foreach ($this->outerKeys as $i => $outerKey) {
138
            if (isset($changes[$outerKey])) {
139
                $state->register($this->innerKeys[$i], $changes[$outerKey]);
140
            }
141
        }
142
    }
143
144
    private function checkNullValue(Node $node, State $state, mixed $value): bool
145
    {
146
        if ($value !== null) {
147
            return false;
148
        }
149
        $original = $node->getRelation($this->getName());
150
        // Original is not null
151
        if ($original !== null) {
152
            // Reset keys
153
            foreach ($this->innerKeys as $innerKey) {
154
                $state->register($innerKey, null);
155
            }
156
        }
157
158
        $node->setRelation($this->getName(), null);
159
        $state->setRelationStatus($this->getName(), RelationInterface::STATUS_RESOLVED);
160
        return true;
161
    }
162
}
163