RefersTo::queue()   C
last analyzed

Complexity

Conditions 17
Paths 40

Size

Total Lines 53
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 28
CRAP Score 18.589

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 17
eloc 37
nc 40
nop 2
dl 0
loc 53
ccs 28
cts 34
cp 0.8235
crap 18.589
rs 5.2166
c 1
b 0
f 0

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
        $node = $tuple->node;
36 406
        $tuple->state->setRelation($this->getName(), $related);
37
38 406
        if ($related instanceof ReferenceInterface && $this->resolve($related, false) !== null) {
39 8
            $related = $related->getValue();
40 8
            $tuple->state->setRelation($this->getName(), $related);
41
        }
42 406
        if ($this->checkNullValue($node, $tuple->state, $related)) {
43 142
            return;
44
        }
45 376
        $this->registerWaitingFields($tuple->state, false);
46 376
        if ($related instanceof ReferenceInterface) {
47 96
            $tuple->state->setRelationStatus($this->getName(), RelationInterface::STATUS_DEFERRED);
48 96
            return;
49
        }
50
51 352
        $tuple->state->setRelationStatus($this->getName(), RelationInterface::STATUS_PROCESS);
52 352
        $rTuple = $pool->offsetGet($related);
53 352
        if ($rTuple === null && $this->isCascade()) {
54 320
            $pool->attachStore($related, false, null, null, false);
55
        }
56
    }
57
58 424
    public function queue(Pool $pool, Tuple $tuple): void
59
    {
60 424
        $node = $tuple->node;
61 424
        $related = $tuple->state->getRelation($this->getName());
62
63 424
        if ($related instanceof ReferenceInterface && ($related->hasValue() || $this->resolve($related, false) !== null)) {
64 8
            $related = $related->getValue();
65 8
            $tuple->state->setRelation($this->getName(), $related);
66
        }
67 424
        if ($related instanceof ReferenceInterface) {
68 88
            $scope = $related->getScope();
69 88
            if (array_intersect($this->outerKeys, array_keys($scope))) {
70 88
                foreach ($this->outerKeys as $i => $outerKey) {
71 88
                    $tuple->state->register($this->innerKeys[$i], $scope[$outerKey]);
72
                }
73 88
                $node->setRelation($this->getName(), $related);
74 88
                $tuple->state->setRelationStatus($this->getName(), RelationInterface::STATUS_RESOLVED);
75 88
                return;
76
            }
77
        }
78 408
        if ($this->checkNullValue($tuple->node, $tuple->state, $related)) {
79 56
            return;
80
        }
81 352
        $rTuple = $pool->offsetGet($related);
82 352
        if ($rTuple === null) {
83
            if ($this->isCascade()) {
84
                // todo: cascade true?
85
                $rTuple = $pool->attachStore($related, false, null, null, false);
86
            } elseif (
87
                $tuple->state->getRelationStatus($this->getName()) !== RelationInterface::STATUS_DEFERRED
88
                || $tuple->status !== Tuple::STATUS_PROPOSED
89
            ) {
90
                $tuple->state->setRelationStatus($this->getName(), RelationInterface::STATUS_DEFERRED);
91
                return;
92
            } else {
93
                $tuple->state->setRelationStatus($this->getName(), RelationInterface::STATUS_RESOLVED);
94
                return;
95 352
            }
96 208
        }
97 208
98 352
        if ($rTuple->status === Tuple::STATUS_PROCESSED
99
            || ($rTuple->status > Tuple::STATUS_PREPARING
100 328
                && $rTuple->state->getStatus() !== node::NEW
101 328
                && \array_intersect($this->outerKeys, $rTuple->state->getWaitingFields()) === [])
102 328
        ) {
103 328
            $this->pullValues($tuple->state, $rTuple->state);
104
            $node->setRelation($this->getName(), $related);
105
            $tuple->state->setRelationStatus($this->getName(), RelationInterface::STATUS_RESOLVED);
106 192
            return;
107 192
        }
108
109
        if ($tuple->status !== Tuple::STATUS_PREPARING) {
110
            $tuple->state->setRelationStatus($this->getName(), RelationInterface::STATUS_DEFERRED);
111 328
        }
112
    }
113 328
114 328
    private function pullValues(State $state, State $rState): void
115 328
    {
116 328
        $changes = $rState->getTransactionData();
117
        foreach ($this->outerKeys as $i => $outerKey) {
118
            if (isset($changes[$outerKey])) {
119
                $state->register($this->innerKeys[$i], $changes[$outerKey]);
120
            }
121 454
        }
122
    }
123 454
124 376
    private function checkNullValue(Node $node, State $state, mixed $value): bool
125
    {
126 198
        if ($value !== null) {
127
            return false;
128 198
        }
129
        $original = $node->getRelation($this->getName());
130 96
        // Original is not null
131 96
        if ($original !== null) {
132
            // Reset keys
133
            foreach ($this->innerKeys as $innerKey) {
134
                $state->register($innerKey, null);
135 198
            }
136 198
        }
137 198
138
        $node->setRelation($this->getName(), null);
139
        $state->setRelationStatus($this->getName(), RelationInterface::STATUS_RESOLVED);
140
        return true;
141
    }
142
}
143