Completed
Push — master ( c3fb1e...80f01e )
by Jesse
03:03
created

HasMany::manyProxiesInThe()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 2
nop 1
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stratadox\Hydration\Mapper\Instruction\Relation;
6
7
use function class_implements;
8
use function in_array;
9
use Stratadox\Collection\Alterable;
10
use Stratadox\Hydration\Mapper\NoContainerAvailable;
11
use Stratadox\Hydration\Mapper\NoLoaderAvailable;
12
use Stratadox\Hydration\Mapping\Property\Relationship\HasManyNested;
13
use Stratadox\Hydration\Mapping\Property\Relationship\HasManyProxies;
14
use Stratadox\Hydration\Mapping\Property\Relationship\HasOneProxy;
15
use Stratadox\HydrationMapping\MapsProperty;
16
use Stratadox\Hydrator\ArrayHydrator;
17
use Stratadox\Hydrator\Hydrates;
18
use Stratadox\Hydrator\SimpleHydrator;
19
use Stratadox\Hydrator\VariadicConstructor;
20
use Stratadox\Proxy\AlterableCollectionEntryUpdaterFactory;
21
use Stratadox\Proxy\ArrayEntryUpdaterFactory;
22
use Stratadox\Proxy\ProducesOwnerUpdaters;
23
use Stratadox\Proxy\PropertyUpdaterFactory;
24
use Stratadox\Proxy\Proxy;
25
use Stratadox\Proxy\ProxyFactory;
26
27
/**
28
 * Indicates a polygamic relationship in the property.
29
 *
30
 * @package Stratadox\Hydrate
31
 * @author Stratadox
32
 */
33
final class HasMany extends Relationship
34
{
35
    public function followFor(string $property) : MapsProperty
36
    {
37
        if ($this->shouldNest) {
38
            return $this->manyNestedInThe($property);
39
        }
40
        if ($this->isImplementingThe(Proxy::class, $this->class)) {
41
            return $this->manyProxiesInThe($property);
42
        }
43
        return $this->oneProxyInThe($property);
44
    }
45
46
    private function manyNestedInThe(string $property) : MapsProperty
47
    {
48
        return HasManyNested::inPropertyWithDifferentKey($property,
49
            $this->keyOr($property),
50
            $this->container(),
51
            $this->hydrator()
52
        );
53
    }
54
55
    private function manyProxiesInThe(string $property) : MapsProperty
56
    {
57
        if (!isset($this->loader)) {
58
            throw NoLoaderAvailable::whilstRequiredFor($this->class);
59
        }
60
        return HasManyProxies::inPropertyWithDifferentKey($property,
61
            $this->keyOr($property),
62
            $this->container(),
63
            ProxyFactory::fromThis(
64
                SimpleHydrator::forThe($this->class),
65
                $this->loader,
66
                $this->updaterFactory()
67
            )
68
        );
69
    }
70
71
    private function oneProxyInThe(string $property) : MapsProperty
72
    {
73
        if (!isset($this->loader)) {
74
            throw NoLoaderAvailable::whilstRequiredFor($this->class);
75
        }
76
        if (!isset($this->container)) {
77
            throw NoContainerAvailable::whilstRequiredFor($this->class);
78
        }
79
        return HasOneProxy::inProperty($property,
80
            ProxyFactory::fromThis(
81
                SimpleHydrator::forThe($this->container),
82
                $this->loader,
83
                new PropertyUpdaterFactory
84
            )
85
        );
86
    }
87
88
    private function container() : Hydrates
89
    {
90
        if (isset($this->container)) {
91
            return VariadicConstructor::forThe($this->container);
92
        }
93
        return ArrayHydrator::create();
94
    }
95
96
    private function updaterFactory() : ProducesOwnerUpdaters
97
    {
98
        if ($this->isImplementingThe(Alterable::class, $this->container)) {
99
            return new AlterableCollectionEntryUpdaterFactory;
100
        }
101
        return new ArrayEntryUpdaterFactory;
102
    }
103
104
    private function isImplementingThe(string $interface, ?string $class) : bool
105
    {
106
        return isset($class) && in_array($interface, class_implements($class));
107
    }
108
}
109