Provider   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 185
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 22
eloc 59
dl 0
loc 185
ccs 67
cts 67
cp 1
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A checkClass() 0 6 2
A toId() 0 18 4
A build() 0 12 2
A hasId() 0 7 1
A getIds() 0 7 1
A get() 0 19 3
A getDataSet() 0 3 1
A getAll() 0 17 4
A hydrate() 0 13 3
A getAssociative() 0 11 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Byscripts\StaticEntity;
5
6
class Provider implements ProviderInterface
7
{
8
    static private $instances = [];
9
10
    /**
11
     * @param string $className
12
     * @param mixed  $id
13
     *
14
     * @return StaticEntityInterface
15
     */
16 8
    static public function get(string $className, $id): StaticEntityInterface
17
    {
18 8
        if (isset(self::$instances[$className][$id])) {
19 5
            return self::$instances[$className][$id];
20
        }
21
22 3
        self::checkClass($className);
23
24 3
        $dataSet = self::getDataSet($className);
25
26 3
        if (!isset($dataSet[$id])) {
27 2
            throw new \InvalidArgumentException(
28 2
                sprintf('Unable to find data for class "%s" with ID "%s"', $className, $id)
29
            );
30
        }
31
32 1
        self::build($className, $id, $dataSet[$id]);
33
34 1
        return self::$instances[$className][$id];
35
    }
36
37
    /**
38
     * @param string $className
39
     *
40
     * @return array
41
     */
42 7
    static public function getAll(string $className): array
43
    {
44 7
        self::checkClass($className);
45
46 6
        $dataSet = self::getDataSet($className);
47
48 6
        if (isset(self::$instances[$className]) && count($dataSet) === count(self::$instances[$className])) {
49 3
            return self::$instances[$className];
50
        }
51
52 3
        $ids = array_keys($dataSet);
53
54 3
        foreach ($ids as $id) {
55 3
            self::build($className, $id, $dataSet[$id]);
56
        }
57
58 1
        return self::$instances[$className];
59
    }
60
61
    /**
62
     * @param string $className
63
     * @param mixed  $id
64
     *
65
     * @return bool
66
     */
67 6
    static public function hasId(string $className, $id): bool
68
    {
69 6
        self::checkClass($className);
70
71 6
        $dataSet = self::getDataSet($className);
72
73 6
        return isset($dataSet[$id]);
74
    }
75
76
    /**
77
     * @param string $className
78
     * @param mixed  $classOrId
79
     *
80
     * @return mixed
81
     */
82 6
    static public function toId(string $className, $classOrId)
83
    {
84 6
        self::checkClass($className);
85
86 6
        if ($classOrId instanceof StaticEntityInterface) {
87 2
            return $classOrId->getId();
88 6
        } elseif (is_object($classOrId)) {
89 2
            throw new \InvalidArgumentException(
90 2
                sprintf('Class "%s" does not implement "%s"', get_class(), StaticEntityInterface::class)
91
            );
92
        }
93
94 4
        if (self::hasId($className, $classOrId)) {
95 2
            return $classOrId;
96
        }
97
98 2
        throw new \InvalidArgumentException(
99 2
            sprintf('Unable to find ID "%s" in dataSet of class "%s"', $classOrId, $className)
100
        );
101
    }
102
103
    /**
104
     * @param string $className
105
     * @param string $key
106
     *
107
     * @return array
108
     */
109 2
    static public function getAssociative(string $className, string $key = 'name'): array
110
    {
111 2
        self::checkClass($className);
112
113 2
        $dataSet = self::getDataSet($className);
114
115 2
        return array_map(
116 2
            function ($data) use ($key) {
117 2
                return $data[$key];
118 2
            },
119 2
            $dataSet
120
        );
121
    }
122
123
    /**
124
     * @param string $className
125
     *
126
     * @return array
127
     */
128 2
    static public function getIds(string $className): array
129
    {
130 2
        self::checkClass($className);
131
132 2
        $dataSet = self::getDataSet($className);
133
134 2
        return array_keys($dataSet);
135
    }
136
137
    /**
138
     * @param string $className
139
     */
140 22
    static private function checkClass(string $className): void
141
    {
142 22
        $interfaceName = StaticEntityInterface::class;
143
144 22
        if (!is_subclass_of($className, $interfaceName)) {
145 1
            throw new \InvalidArgumentException("${className} must implements ${interfaceName}");
146
        }
147 21
    }
148
149
    /**
150
     * @param string $className
151
     *
152
     * @return array
153
     */
154
    static private function getDataSet(string $className): array
155
    {
156 19
        return call_user_func([$className, 'getDataSet']);
157
    }
158
159
    /**
160
     * @param string $className
161
     * @param mixed  $id
162
     * @param array  $data
163
     */
164
    static private function build(string $className, $id, array $data): void
165
    {
166 4
        if (isset(self::$instances[$className][$id])) {
167 1
            return;
168
        }
169
170 4
        $instance = new $className();
171
172 4
        $data['id'] = $id;
173 4
        self::hydrate($instance, $data);
174
175 2
        self::$instances[$className][$id] = $instance;
176 2
    }
177
178
    static private function hydrate(StaticEntityInterface $instance, array $data): void
179
    {
180 4
        $reflectionClass = new \ReflectionClass($instance);
181
182 4
        foreach ($data as $key => $value) {
183 4
            if (!$reflectionClass->hasProperty($key)) {
184 2
                throw new \InvalidArgumentException(
185 2
                    sprintf('Class "%s" has no property "%s"', $reflectionClass->name, $key)
186
                );
187
            }
188 2
            $property = $reflectionClass->getProperty($key);
189 2
            $property->setAccessible(true);
190 2
            $property->setValue($instance, $value);
191
        }
192 2
    }
193
}
194