RefersTo::queue()   D
last analyzed

Complexity

Conditions 18
Paths 41

Size

Total Lines 62
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 62
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
59
        if ($related instanceof ReferenceInterface) {
60 424
            $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_DEFERRED);
61 424
            return;
62
        }
63 424
64 8
        $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_PROCESS);
65 8
        $rTuple = $pool->offsetGet($related);
66
        if ($rTuple === null && $this->isCascade()) {
67 424
            $pool->attachStore($related, false, null, null, false);
68 88
        }
69 88
    }
70 88
71 88
    public function queue(Pool $pool, Tuple $tuple): void
72
    {
73 88
        $state = $tuple->state;
74 88
        $relName = $this->getName();
75 88
76
        if (!$state->hasRelation($relName)) {
77
            $state->setRelationStatus($relName, RelationInterface::STATUS_RESOLVED);
78 408
            return;
79 56
        }
80
81 352
        $node = $tuple->node;
82 352
        $related = $tuple->state->getRelation($relName);
83
84
        if ($related instanceof ReferenceInterface && ($related->hasValue() || $this->resolve($related, false) !== null)) {
85
            $related = $related->getValue();
86
            $tuple->state->setRelation($relName, $related);
87
        }
88
        if ($related instanceof ReferenceInterface) {
89
            $scope = $related->getScope();
90
            if (\array_intersect($this->outerKeys, \array_keys($scope))) {
91
                foreach ($this->outerKeys as $i => $outerKey) {
92
                    $tuple->state->register($this->innerKeys[$i], $scope[$outerKey]);
93
                }
94
                $node->setRelation($relName, $related);
95 352
                $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_RESOLVED);
96 208
                return;
97 208
            }
98 352
        }
99
        if ($this->checkNullValue($tuple->node, $tuple->state, $related)) {
100 328
            return;
101 328
        }
102 328
103 328
        $rTuple = $pool->offsetGet($related);
104
        if ($rTuple === null) {
105
            if ($this->isCascade()) {
106 192
                // todo: cascade true?
107 192
                $rTuple = $pool->attachStore($related, false, null, null, false);
108
            } elseif (
109
                $tuple->state->getRelationStatus($relName) !== RelationInterface::STATUS_DEFERRED
110
                || $tuple->status !== Tuple::STATUS_PROPOSED_RESOLVED
111 328
            ) {
112
                $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_DEFERRED);
113 328
                return;
114 328
            } else {
115 328
                $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_RESOLVED);
116 328
                return;
117
            }
118
        }
119
120
        if ($rTuple->status === Tuple::STATUS_PROCESSED
121 454
            || ($rTuple->status > Tuple::STATUS_PREPARING
122
                && $rTuple->state->getStatus() !== node::NEW
123 454
                && \array_intersect($this->outerKeys, $rTuple->state->getWaitingFields()) === [])
124 376
        ) {
125
            $this->pullValues($tuple->state, $rTuple->state);
126 198
            $node->setRelation($relName, $related);
127
            $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_RESOLVED);
128 198
            return;
129
        }
130 96
131 96
        if ($tuple->status !== Tuple::STATUS_PREPARING) {
132
            $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_DEFERRED);
133
        }
134
    }
135 198
136 198
    private function pullValues(State $state, State $rState): void
137 198
    {
138
        $changes = $rState->getTransactionData();
139
        foreach ($this->outerKeys as $i => $outerKey) {
140
            if (isset($changes[$outerKey])) {
141
                $state->register($this->innerKeys[$i], $changes[$outerKey]);
142
            }
143
        }
144
    }
145
146
    private function checkNullValue(Node $node, State $state, mixed $value): bool
147
    {
148
        if ($value !== null) {
149
            return false;
150
        }
151
        $original = $node->getRelation($this->getName());
152
        // Original is not null
153
        if ($original !== null) {
154
            // Reset keys
155
            foreach ($this->innerKeys as $innerKey) {
156
                $state->register($innerKey, null);
157
            }
158
        }
159
160
        $node->setRelation($this->getName(), null);
161
        $state->setRelationStatus($this->getName(), RelationInterface::STATUS_RESOLVED);
162
        return true;
163
    }
164
}
165