Completed
Push — master ( 7dd3b4...978843 )
by Jesse
03:52
created

Mapper::property()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Stratadox\Hydration\Mapper;
5
6
use Stratadox\Hydration\Mapper\Instruction\Is;
7
use Stratadox\Hydration\Mapping\Properties;
8
use Stratadox\HydrationMapper\InstructsHowToMap;
9
use Stratadox\HydrationMapper\MakesMap;
10
use Stratadox\HydrationMapper\RepresentsChoice;
11
use Stratadox\Hydrator\Hydrates;
12
use Stratadox\Hydrator\MappedHydrator;
13
use Stratadox\Hydrator\OneOfTheseHydrators;
14
use Stratadox\Instantiator\CannotInstantiateThis;
15
use function array_map;
16
17
/**
18
 * Builds a mapped hydrator, configured with mappings for the properties.
19
 *
20
 * @package Stratadox\Hydrate
21
 * @author  Stratadox
22
 */
23
final class Mapper implements MakesMap
24
{
25
    /** @var string */
26
    private $name;
27
28
    /** @var InstructsHowToMap[] */
29
    private $properties;
30
31
    /** @var string|null */
32
    private $decisionKey;
33
34
    /** @var RepresentsChoice[] */
35
    private $choices;
36
37
    private function __construct(
38
        string $name,
39
        array $properties = [],
40
        string $decisionKey = null,
41
        array $choices = []
42
    ) {
43
        $this->name = $name;
44
        $this->properties = $properties;
45
        $this->decisionKey = $decisionKey;
46
        $this->choices = $choices;
47
    }
48
49
    /**
50
     * Creates a builder that produces a mapped hydrator for a class.
51
     *
52
     * @see MappedHydrator
53
     * @param string $className The fully qualified name of the class to produce
54
     *                          a mapped hydrator for.
55
     * @return MakesMap         The builder for the mapped hydrator.
56
     */
57
    public static function forThe(string $className): MakesMap
58
    {
59
        return new self($className);
60
    }
61
62
    /** @inheritdoc */
63
    public function property(
64
        string $property,
65
        InstructsHowToMap $instruction = null
66
    ): MakesMap {
67
        return new self($this->name, $this->add($property, $instruction));
68
    }
69
70
    /** @inheritdoc */
71
    public function selectBy(
72
        string $decisionKey,
73
        array $choices
74
    ): MakesMap {
75
        return new self('', [], $decisionKey, $choices);
76
    }
77
78
    /** @inheritdoc */
79
    public function finish(): Hydrates
80
    {
81
        if (isset($this->decisionKey)) {
82
            return OneOfTheseHydrators::decideBasedOnThe(
83
                $this->decisionKey,
84
                array_map(function (RepresentsChoice $choice): Hydrates {
85
                    return $choice->finish();
86
                }, $this->choices)
87
            );
88
        }
89
        $class = $this->name;
90
        $properties = [];
91
        foreach ($this->properties as $name => $instruction) {
92
            $properties[] = $instruction->followFor($name);
93
        }
94
        try {
95
            return MappedHydrator::forThe($class, Properties::map(...$properties));
96
        } catch (CannotInstantiateThis $problem) {
97
            throw NoSuchClass::couldNotLoad($class);
98
        }
99
    }
100
101
    /**
102
     * Adds a property to the mapper.
103
     *
104
     * @param string                 $property    The name of the property.
105
     * @param InstructsHowToMap|null $instruction The instruction to follow.
106
     * @return InstructsHowToMap[]                The map of properties to
107
     *                                            mapping instructions.
108
     */
109
    private function add(
110
        string $property,
111
        ?InstructsHowToMap $instruction
112
    ): array {
113
        return $this->properties + [$property => $instruction ?: Is::string()];
114
    }
115
}
116