ShadowBelongsTo::isNullable()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 1
cts 1
cp 1
crap 1
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cycle\ORM\Relation;
6
7
use Cycle\ORM\Heap\State;
8
use Cycle\ORM\Relation;
9
use Cycle\ORM\Transaction\Pool;
10
use Cycle\ORM\Transaction\Tuple;
11
12
/**
13
 * @internal
14
 */
15
class ShadowBelongsTo implements ReversedRelationInterface, DependencyInterface
16
{
17
    private string $name;
18
    private string $target;
19
    private array $schema;
20
    private array $innerKeys;
21
    private bool $cascade;
22
23
    public function __construct(string $name, string $target, array $schema)
24 3648
    {
25
        $this->name = $target . '.' . $name . ':' . $schema[Relation::TARGET];
26 3648
        $this->target = $target;
27 3648
        $this->schema = $schema;
28 3648
        $this->innerKeys = (array) ($schema[Relation::SCHEMA][Relation::OUTER_KEY] ?? []);
29 3648
        $this->cascade = (bool) ($schema[Relation::SCHEMA][Relation::CASCADE] ?? false);
30 3648
    }
31
32
    public function getInnerKeys(): array
33
    {
34
        return $this->innerKeys;
35
    }
36
37
    public function prepare(Pool $pool, Tuple $tuple, mixed $related, bool $load = true): void
38
    {
39
        $tuple->state->setRelation($this->getName(), $related);
40
        $this->registerWaitingFields($tuple->state, !$this->isNullable());
41
        $tuple->state->setRelationStatus($this->getName(), RelationInterface::STATUS_PROCESS);
42
    }
43
44
    public function queue(Pool $pool, Tuple $tuple): void
45 1264
    {
46
        $status = $tuple->state->getRelationStatus($this->getName());
47 1264
        if ($status === RelationInterface::STATUS_PREPARE && $this->isNullable()) {
48 1264
            $tuple->state->setRelationStatus($this->getName(), RelationInterface::STATUS_DEFERRED);
49 214
        }
50
        if ($tuple->status >= Tuple::STATUS_WAITED) {
51 1264
            // Check fields
52
            if ($this->isNullable() || $this->checkFieldsExists($tuple->state)) {
53 1152
                $tuple->state->setRelationStatus($this->getName(), RelationInterface::STATUS_RESOLVED);
54 1120
            }
55
        }
56
    }
57
58
    public function getName(): string
59 3648
    {
60
        return $this->name;
61 3648
    }
62
63
    public function getTarget(): string
64
    {
65
        return $this->target;
66
    }
67
68
    public function isCascade(): bool
69
    {
70
        return $this->cascade;
71
    }
72
73
    public function isNullable(): bool
74 1264
    {
75
        return (bool) ($this->schema[Relation::SCHEMA][Relation::NULLABLE] ?? false);
76 1264
    }
77
78
    private function checkFieldsExists(State $state): bool
79 1016
    {
80
        $data = $state->getData();
81 1016
        foreach ($this->innerKeys as $key) {
82 1016
            if (!isset($data[$key])) {
83 880
                return false;
84 97
            }
85
        }
86
        return true;
87 984
    }
88
89
    private function registerWaitingFields(State $state, bool $required = true): void
90
    {
91
        foreach ($this->innerKeys as $key) {
92
            $state->waitField($key, $required);
93
        }
94
    }
95
}
96