Completed
Pull Request — master (#88)
by Julien
02:57
created

Mapping   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 217
Duplicated Lines 0 %

Test Coverage

Coverage 96.77%

Importance

Changes 0
Metric Value
eloc 67
dl 0
loc 217
ccs 60
cts 62
cp 0.9677
rs 9.68
c 0
b 0
f 0
wmc 34

16 Methods

Rating   Name   Duplication   Size   Complexity  
A getIdPrefix() 0 3 1
A parseKeyFromId() 0 10 2
A getConfig() 0 3 1
A getKeyFromModel() 0 10 3
A checkMappingExistence() 0 17 5
A getModelName() 0 8 1
A tryGetClassMetadataById() 0 11 3
A getMappingKeys() 0 5 1
A getKeyFromId() 0 10 2
A setMapping() 0 5 1
A getClassMetadataByKey() 0 9 3
A setConfig() 0 5 1
A hasClassMetadata() 0 9 3
A removePrefix() 0 10 3
A getClassMetadata() 0 9 3
A __construct() 0 5 1
1
<?php
2
3
namespace Mapado\RestClientSdk;
4
5
use Mapado\RestClientSdk\Exception\MappingException;
6
use Mapado\RestClientSdk\Mapping\ClassMetadata;
7
8
/**
9
 * Class Mapping
10
 *
11
 * @author Julien Deniau <[email protected]>
12
 */
13
class Mapping
14
{
15
    public const DEFAULT_CONFIG = ['collectionKey' => 'hydra:member'];
16
17
    /**
18
     * @var string
19
     */
20
    private $idPrefix;
21
22
    /**
23
     * @var int
24
     */
25
    private $idPrefixLength;
26
27
    /**
28
     * @var array<ClassMetadata>
29
     */
30
    private $classMetadataList = [];
31
32
    /**
33
     * @var array
34
     */
35
    private $config;
36
37
    public function __construct(string $idPrefix = '', array $config = [])
38
    {
39 1
        $this->idPrefix = $idPrefix;
40 1
        $this->idPrefixLength = strlen($idPrefix);
41 1
        $this->setConfig($config);
42 1
    }
43
44
    public function getIdPrefix(): string
45
    {
46
        return $this->idPrefix;
47
    }
48
49
    public function getConfig(): array
50
    {
51 1
        return $this->config;
52
    }
53
54
    public function setConfig(array $config): self
55
    {
56 1
        $this->config = array_merge(self::DEFAULT_CONFIG, $config);
57
58 1
        return $this;
59
    }
60
61
    /**
62
     * @param array<ClassMetadata> $classMetadataList
63
     */
64
    public function setMapping(array $classMetadataList): self
65
    {
66 1
        $this->classMetadataList = $classMetadataList;
67
68 1
        return $this;
69
    }
70
71
    /**
72
     * return a model class name for a given key
73
     */
74
    public function getModelName(string $key): string
75
    {
76 1
        $this->checkMappingExistence($key, true);
77
78
        /** @var ClassMetadata */
79 1
        $classMetadata = $this->getClassMetadataByKey($key);
80
81 1
        return $classMetadata->getModelName();
82
    }
83
84
    /**
85
     * return the list of mapping keys
86
     *
87
     * @return array<string>
88
     */
89
    public function getMappingKeys(): array
90
    {
91 1
        return array_map(function (ClassMetadata $classMetadata) {
92 1
            return $classMetadata->getKey();
93 1
        }, $this->classMetadataList);
94
    }
95
96
    /**
97
     * get the key from an id (path)
98
     */
99
    public function getKeyFromId(string $id): string
100
    {
101 1
        $key = $this->parseKeyFromId($id);
102 1
        if (null === $key) {
103
            throw new MappingException("Unable to parse key from id {$id}.");
104
        }
105
106 1
        $this->checkMappingExistence($key);
107
108 1
        return $key;
109
    }
110
111
    /**
112
     * @param string $modelName model name
113
     *
114
     * @throws MappingException
115
     */
116
    public function getKeyFromModel(string $modelName): string
117
    {
118 1
        foreach ($this->classMetadataList as $classMetadata) {
119 1
            if ($modelName === $classMetadata->getModelName()) {
120 1
                return $classMetadata->getKey();
121
            }
122
        }
123
124 1
        throw new MappingException(
125 1
            'Model name ' . $modelName . ' not found in mapping'
126
        );
127
    }
128
129
    /**
130
     * getClassMetadata for model name
131
     *
132
     * @throws MappingException
133
     */
134
    public function getClassMetadata(string $modelName): ClassMetadata
135
    {
136 1
        foreach ($this->classMetadataList as $classMetadata) {
137 1
            if ($modelName === $classMetadata->getModelName()) {
138 1
                return $classMetadata;
139
            }
140
        }
141
142 1
        throw new MappingException($modelName . ' model is not mapped');
143
    }
144
145
    /**
146
     * getClassMetadata for id
147
     */
148
    public function tryGetClassMetadataById(string $id): ?ClassMetadata
149
    {
150 1
        $key = $this->parseKeyFromId($id);
151
152 1
        foreach ($this->classMetadataList as $classMetadata) {
153 1
            if ($key === $classMetadata->getKey()) {
154 1
                return $classMetadata;
155
            }
156
        }
157
158 1
        return null;
159
    }
160
161
    public function hasClassMetadata(string $modelName): bool
162
    {
163 1
        foreach ($this->classMetadataList as $classMetadata) {
164 1
            if ($modelName === $classMetadata->getModelName()) {
165 1
                return true;
166
            }
167
        }
168
169 1
        return false;
170
    }
171
172
    public function getClassMetadataByKey(string $key): ?ClassMetadata
173
    {
174 1
        foreach ($this->classMetadataList as $classMetadata) {
175 1
            if ($key === $classMetadata->getKey()) {
176 1
                return $classMetadata;
177
            }
178
        }
179
180 1
        return null;
181
    }
182
183
    /**
184
     * Parse the key from an id (path)
185
     */
186
    private function parseKeyFromId(string $id): ?string
187
    {
188 1
        $id = $this->removePrefix($id);
189
190 1
        $matches = [];
191 1
        if (1 === preg_match('|/([^/]+)/[^/]+$|', $id, $matches)) {
192 1
            return $matches[1];
193
        }
194
195 1
        return null;
196
    }
197
198
    private function checkMappingExistence(
199
        string $key,
200
        bool $checkModelName = false
201
    ): void {
202 1
        if (empty($key)) {
203 1
            throw new MappingException('key is not set');
204
        }
205
206 1
        $metadata = $this->getClassMetadataByKey($key);
207 1
        if (!$metadata) {
208 1
            throw new MappingException($key . ' key is not mapped');
209
        }
210
211 1
        if ($checkModelName) {
212 1
            if ('' === $metadata->getModelName()) {
213 1
                throw new MappingException(
214 1
                    $key . ' key is mapped but the model name is empty'
215
                );
216
            }
217
        }
218 1
    }
219
220
    private function removePrefix(string $value): string
221
    {
222
        if (
223 1
            ($this->idPrefixLength > 0) &&
224 1
            (0 === strpos($value, $this->idPrefix))
225
        ) {
226 1
            return substr($value, $this->idPrefixLength);
227
        }
228
229 1
        return $value;
230
    }
231
}
232