Completed
Push — master ( 9b6403...80a993 )
by Jesse
02:09
created

HasMany::followFor()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 3
nop 1
dl 0
loc 9
rs 9.6666
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\Hydrates;
11
use Stratadox\Hydration\Hydrator\ArrayHydrator;
12
use Stratadox\Hydration\Hydrator\SimpleHydrator;
13
use Stratadox\Hydration\Hydrator\VariadicConstructor;
14
use Stratadox\Hydration\Mapper\NoContainerAvailable;
15
use Stratadox\Hydration\Mapper\NoLoaderAvailable;
16
use Stratadox\Hydration\Mapping\Property\Relationship\HasManyNested;
17
use Stratadox\Hydration\Mapping\Property\Relationship\HasManyProxies;
18
use Stratadox\Hydration\Mapping\Property\Relationship\HasOneProxy;
19
use Stratadox\Hydration\MapsProperty;
20
use Stratadox\Hydration\ProducesOwnerUpdaters;
21
use Stratadox\Hydration\Proxy;
22
use Stratadox\Hydration\Proxying\AlterableCollectionEntryUpdaterFactory;
23
use Stratadox\Hydration\Proxying\ArrayEntryUpdaterFactory;
24
use Stratadox\Hydration\Proxying\PropertyUpdaterFactory;
25
use Stratadox\Hydration\Proxying\ProxyFactory;
26
27
final class HasMany extends Relationship
28
{
29
    public function followFor(string $property) : MapsProperty
30
    {
31
        if ($this->shouldNest) {
32
            return $this->manyNestedInThe($property);
33
        }
34
        if ($this->implements(Proxy::class, $this->class)) {
35
            return $this->manyProxiesInThe($property);
36
        }
37
        return $this->oneProxyInThe($property);
38
    }
39
40
    private function manyNestedInThe(string $property) : MapsProperty
41
    {
42
        return HasManyNested::inPropertyWithDifferentKey($property,
43
            $this->keyOr($property),
44
            $this->container(),
45
            $this->hydrator()
46
        );
47
    }
48
49
    private function manyProxiesInThe(string $property) : MapsProperty
50
    {
51
        $this->needsALoader();
52
        return HasManyProxies::inPropertyWithDifferentKey($property,
53
            $this->keyOr($property),
54
            $this->container(),
55
            ProxyFactory::fromThis(
56
                SimpleHydrator::forThe($this->class),
57
                $this->loader,
0 ignored issues
show
Bug introduced by
It seems like $this->loader can also be of type null; however, parameter $loaderFactory of Stratadox\Hydration\Prox...roxyFactory::fromThis() does only seem to accept Stratadox\Hydration\ProducesProxyLoaders, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

57
                /** @scrutinizer ignore-type */ $this->loader,
Loading history...
58
                $this->updaterFactory()
59
            )
60
        );
61
    }
62
63
    private function oneProxyInThe(string $property) : MapsProperty
64
    {
65
        $this->needsAContainer();
66
        $this->needsALoader();
67
        return HasOneProxy::inProperty($property,
68
            ProxyFactory::fromThis(
69
                SimpleHydrator::forThe($this->container),
0 ignored issues
show
Bug introduced by
It seems like $this->container can also be of type null; however, parameter $class of Stratadox\Hydration\Hydr...impleHydrator::forThe() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

69
                SimpleHydrator::forThe(/** @scrutinizer ignore-type */ $this->container),
Loading history...
70
                $this->loader,
0 ignored issues
show
Bug introduced by
It seems like $this->loader can also be of type null; however, parameter $loaderFactory of Stratadox\Hydration\Prox...roxyFactory::fromThis() does only seem to accept Stratadox\Hydration\ProducesProxyLoaders, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

70
                /** @scrutinizer ignore-type */ $this->loader,
Loading history...
71
                new PropertyUpdaterFactory
72
            )
73
        );
74
    }
75
76
    private function container() : Hydrates
77
    {
78
        if (isset($this->container)) {
79
            return VariadicConstructor::forThe($this->container);
80
        }
81
        return ArrayHydrator::create();
82
    }
83
84
    private function updaterFactory() : ProducesOwnerUpdaters
85
    {
86
        if ($this->implements(Alterable::class, $this->container)) {
87
            return new AlterableCollectionEntryUpdaterFactory;
88
        }
89
        return new ArrayEntryUpdaterFactory;
90
    }
91
92
    private function implements(string $interface, ?string $class)
93
    {
94
        return isset($class) && in_array($interface, class_implements($class));
95
    }
96
97
    private function needsALoader() : void
98
    {
99
        if (!isset($this->loader)) {
100
            throw NoLoaderAvailable::for($this->class);
101
        }
102
    }
103
104
    private function needsAContainer() : void
105
    {
106
        if (!isset($this->container)) {
107
            throw NoContainerAvailable::for($this->class);
108
        }
109
    }
110
}
111