Mapping::removePrefix()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

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