Completed
Push — master ( 9e9e7e...b5260b )
by Jesse
02:00
created

InCase::mustKnowTheIdentityColumnsFor()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 2
eloc 2
nc 2
nop 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Stratadox\TableLoader;
5
6
use function array_merge;
7
use function count;
8
use function is_null;
9
use Stratadox\Hydration\Mapper\Mapper;
10
use Stratadox\Hydrator\ArrayHydrator;
11
use Stratadox\Hydrator\Hydrates;
12
use Stratadox\Hydrator\SimpleHydrator;
13
use Stratadox\Hydrator\VariadicConstructor;
14
15
final class InCase implements LoadsWhenTriggered
16
{
17
    private $trigger;
18
    private $class;
19
    private $identityColumnsFor = [];
20
    private $properties = [];
21
    private $relation = [];
22
    private $label;
23
24
    private function __construct(string $trigger)
25
    {
26
        $this->trigger = $trigger;
27
    }
28
29
    public static function of(
30
        string $trigger
31
    ): LoadsWhenTriggered {
32
        return new self($trigger);
33
    }
34
35
    /** @inheritdoc */
36
    public function as(
37
        string $class,
38
        array $properties = []
39
    ): LoadsWhenTriggered {
40
        $new = clone $this;
41
        $new->class = $class;
42
        $new->properties = $properties;
43
        return $new;
44
    }
45
46
    /** @inheritdoc */
47
    public function with(array $properties): LoadsWhenTriggered
48
    {
49
        $new = clone $this;
50
        $new->properties = array_merge($this->properties, $properties);
51
        return $new;
52
    }
53
54
    /** @inheritdoc */
55
    public function havingOne(
56
        string $property,
57
        string $label = null
58
    ): LoadsWhenTriggered {
59
        $new = clone $this;
60
        $new->relation[$label ?: $property] = HasOne::in($property);
61
        return $new;
62
    }
63
64
    /** @inheritdoc */
65
    public function havingMany(
66
        string $property,
67
        string $label,
68
        string $collectionClass = null
69
    ): LoadsWhenTriggered {
70
        $hydrator = $collectionClass ?
71
            VariadicConstructor::forThe($collectionClass) :
72
            ArrayHydrator::create();
73
        $new = clone $this;
74
        $new->relation[$label] = HasMany::in($property, $hydrator);
75
        return $new;
76
    }
77
78
    /** @inheritdoc */
79
    public function identifying(
80
        string $label,
81
        string ...$columns
82
    ): LoadsWhenTriggered {
83
        $new = clone $this;
84
        $new->identityColumnsFor[$label] = $columns;
85
        return $new;
86
    }
87
88
    /** @inheritdoc */
89
    public function labeled(string $label): LoadsWhenTriggered
90
    {
91
        $new = clone $this;
92
        $new->label = $label;
93
        return $new;
94
    }
95
96
    /** @inheritdoc */
97
    public function decisionTrigger(): string
98
    {
99
        return $this->trigger;
100
    }
101
102
    /** @inheritdoc */
103
    public function hydrator(): Hydrates
104
    {
105
        if (empty($this->properties)) {
106
            return SimpleHydrator::forThe($this->class);
107
        }
108
        $mapper = Mapper::forThe($this->class);
109
        foreach ($this->properties as $name => $instruction) {
110
            $mapper = $mapper->property($name, $instruction);
111
        }
112
        return $mapper->finish();
113
    }
114
115
    /** @inheritdoc */
116
    public function wiring(): WiresObjects
117
    {
118
        $ownLabel = $this->label;
119
        if (is_null($ownLabel)) {
120
            throw CannotMakeMapping::missingTheLabelFor($this->trigger);
121
        }
122
        $ownId = $this->identityColumnsFor[$ownLabel];
123
        $wires = [];
124
        foreach ($this->relation as $otherLabel => $connectThem) {
125
            $this->mustKnowTheIdentityColumnsFor($otherLabel);
126
            $otherId = $this->identityColumnsFor[$otherLabel];
127
            $wires[] = Wire::it(
128
                From::onlyThe($this->class, $ownLabel, Identified::by(...$ownId)),
129
                To::the($otherLabel, Identified::by(...$otherId)),
130
                $connectThem
131
            );
132
        }
133
        if (count($wires) === 1) {
134
            return $wires[0];
135
        }
136
        return Wired::together(...$wires);
137
    }
138
139
    /** @throws CannotMakeMapping */
140
    private function mustKnowTheIdentityColumnsFor(string $label): void
141
    {
142
        if (!isset($this->identityColumnsFor[$label])) {
143
            throw CannotMakeMapping::missingTheIdentityColumns($label, $this->label);
144
        }
145
    }
146
}
147