Completed
Push — master ( 0d47c0...ecf131 )
by Jesse
05:02
created

HasManyProxies::mustHaveTheKeyInThe()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Stratadox\Hydration\Mapping\Property\Relationship;
5
6
use Stratadox\HydrationMapping\ExposesDataKey;
7
use Stratadox\Hydrator\Hydrates;
8
use Stratadox\Proxy\ProducesProxies;
9
use Throwable;
10
11
/**
12
 * Maps a number to a collection of proxies in an object property.
13
 *
14
 * @package Stratadox\Hydrate
15
 * @author Stratadox
16
 */
17
final class HasManyProxies implements ExposesDataKey
18
{
19
    use KeyRequiring;
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
     * Creates 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
     * Creates a new lazily loading has-many mapping, using the data from a
56
     * specific key.
57
     *
58
     * @param string          $name         The name of 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
    /** @inheritdoc */
74
    public function name() : string
75
    {
76
        return $this->name;
77
    }
78
79
    /** @inheritdoc */
80
    public function key() : string
81
    {
82
        return $this->key;
83
    }
84
85
    /** @inheritdoc */
86
    public function value(array $data, $owner = null)
87
    {
88
        $this->mustHaveTheKeyInThe($data);
89
        $amount = $data[$this->key()];
90
        try {
91
            $proxies = $this->makeSomeProxies($amount, $owner);
92
        } catch (Throwable $exception) {
93
            throw ProxyProductionFailed::tryingToProduceFor($this, $exception);
94
        }
95
        try {
96
            return $this->collection->fromArray($proxies);
97
        } catch (Throwable $exception) {
98
            throw CollectionMappingFailed::tryingToMapCollection($this, $exception);
99
        }
100
    }
101
102
    /**
103
     * Produces the proxies for in the collection.
104
     *
105
     * @param int $amount   The amount of proxies to produce.
106
     * @param object $owner The object that holds a reference to the proxy.
107
     * @return array        List of proxy objects.
108
     */
109
    private function makeSomeProxies(int $amount, $owner): array
110
    {
111
        $proxies = [];
112
        for ($i = 0; $i < $amount; ++$i) {
113
            $proxies[] = $this->proxyBuilder->createFor($owner, $this->name(), $i);
114
        }
115
        return $proxies;
116
    }
117
}
118