Passed
Push — master ( 43c74d...df9319 )
by Jesse
02:15
created

HasManyProxies::inProperty()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 3
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stratadox\Hydration\Mapping\Property\Relationship;
6
7
use Stratadox\Hydration\Mapping\Property\MissingTheKey;
8
use Stratadox\HydrationMapping\ExposesDataKey;
9
use Stratadox\Hydrator\Hydrates;
10
use Stratadox\Proxy\ProducesProxies;
11
use Throwable;
12
13
/**
14
 * Maps a number to a collection of proxies in an object property.
15
 *
16
 * @package Stratadox\Hydrate
17
 * @author Stratadox
18
 */
19
final class HasManyProxies implements ExposesDataKey
20
{
21
    private $name;
22
    private $key;
23
    private $collection;
24
    private $proxyBuilder;
25
26
    private function __construct(
27
        string $name,
28
        string $dataKey,
29
        Hydrates $collectionHydrator,
30
        ProducesProxies $proxyBuilder
31
    ) {
32
        $this->name = $name;
33
        $this->key = $dataKey;
34
        $this->collection = $collectionHydrator;
35
        $this->proxyBuilder = $proxyBuilder;
36
    }
37
38
    /**
39
     * Create a new lazily loaded has-many mapping.
40
     *
41
     * @param string          $name         The name of both the key and the property.
42
     * @param Hydrates        $collection   The hydrator for the collection.
43
     * @param ProducesProxies $proxyBuilder The proxy builder.
44
     * @return self                         The lazy has-many mapping.
45
     */
46
    public static function inProperty(
47
        string $name,
48
        Hydrates $collection,
49
        ProducesProxies $proxyBuilder
50
    ): self {
51
        return new self($name, $name, $collection, $proxyBuilder);
52
    }
53
54
    /**
55
     * Create a new lazily loading has-many mapping, using the data from a
56
     * specific key.
57
     *
58
     * @param string          $name         The name of both the key and the property.
59
     * @param string          $key          The array key to use.
60
     * @param Hydrates        $collection   The hydrator for the collection.
61
     * @param ProducesProxies $proxyBuilder The proxy builder.
62
     * @return self                         The lazy has-many mapping.
63
     */
64
    public static function inPropertyWithDifferentKey(
65
        string $name,
66
        string $key,
67
        Hydrates $collection,
68
        ProducesProxies $proxyBuilder
69
    ): self {
70
        return new self($name, $key, $collection, $proxyBuilder);
71
    }
72
73
    public function name() : string
74
    {
75
        return $this->name;
76
    }
77
78
    public function key() : string
79
    {
80
        return $this->key;
81
    }
82
83
    public function value(array $data, $owner = null)
84
    {
85
        $this->mustHaveTheKeyInThe($data);
86
        $amount = $data[$this->key()];
87
        try {
88
            $proxies = $this->makeSomeProxies($amount, $owner);
89
        } catch (Throwable $exception) {
90
            throw ProxyProductionFailed::tryingToProduceFor($this, $exception);
91
        }
92
        try {
93
            return $this->collection->fromArray($proxies);
94
        } catch (Throwable $exception) {
95
            throw CollectionMappingFailed::tryingToMapCollection($this, $exception);
96
        }
97
    }
98
99
    private function makeSomeProxies(int $amount, $owner): array
100
    {
101
        $proxies = [];
102
        for ($i = 0; $i < $amount; ++$i) {
103
            $proxies[] = $this->proxyBuilder->createFor($owner, $this->name(), $i);
104
        }
105
        return $proxies;
106
    }
107
108
    private function mustHaveTheKeyInThe(array $data): void
109
    {
110
        if (!array_key_exists($this->key(), $data)) {
111
            throw MissingTheKey::inTheInput($data, $this, $this->key());
112
        }
113
    }
114
}
115