GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( 82d40b...14ac0c )
by Baptiste
05:25
created

Primitive   C

Complexity

Total Complexity 54

Size/Duplication

Total Lines 417
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 137
dl 0
loc 417
ccs 160
cts 160
cp 1
rs 6.4799
c 0
b 0
f 0
wmc 54

32 Methods

Rating   Name   Duplication   Size   Complexity  
A get() 0 7 2
A keyType() 0 3 1
A foreach() 0 7 2
A valid() 0 3 1
A current() 0 3 1
A size() 0 3 1
A valueType() 0 3 1
A rewind() 0 3 1
A put() 0 11 1
A offsetExists() 0 3 1
A equals() 0 17 5
A filter() 0 13 3
A groupBy() 0 32 5
A offsetGet() 0 3 1
A count() 0 3 1
A key() 0 3 1
A offsetSet() 0 3 1
A offsetUnset() 0 3 1
A contains() 0 3 1
A clear() 0 7 1
A next() 0 3 1
A __construct() 0 12 2
A remove() 0 12 2
A reduce() 0 7 2
A keys() 0 7 1
A map() 0 25 3
A empty() 0 5 1
A partition() 0 21 3
A join() 0 3 1
A values() 0 3 1
A merge() 0 15 3
A normalizeKey() 0 7 2

How to fix   Complexity   

Complex Class

Complex classes like Primitive often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Primitive, and based on these observations, apply Extract Interface, too.

1
<?php
2
declare(strict_types = 1);
3
4
namespace Innmind\Immutable\Map;
5
6
use Innmind\Immutable\{
7
    MapInterface,
8
    Map,
9
    Type,
10
    Str,
11
    Stream,
12
    StreamInterface,
13
    SetInterface,
14
    Set,
15
    Pair,
16
    Exception\InvalidArgumentException,
17
    Exception\LogicException,
18
    Exception\ElementNotFoundException,
19
    Exception\GroupEmptyMapException
20
};
21
22
final class Primitive implements MapInterface
23
{
24
    private $keyType;
25
    private $valueType;
26
    private $keySpecification;
27
    private $valueSpecification;
28
    private $values;
29
    private $size;
30
31
    /**
32
     * {@inheritdoc}
33
     */
34 144
    public function __construct(string $keyType, string $valueType)
35
    {
36 144
        $this->keySpecification = Type::of($keyType);
37
38 144
        if (!in_array($keyType, ['int', 'integer', 'string'], true)) {
39 2
            throw new LogicException;
40
        }
41
42 142
        $this->valueSpecification = Type::of($valueType);
43 142
        $this->keyType = new Str($keyType);
44 142
        $this->valueType = new Str($valueType);
45 142
        $this->values = [];
46 142
    }
47
48
    /**
49
     * {@inheritdoc}
50
     */
51 46
    public function keyType(): Str
52
    {
53 46
        return $this->keyType;
54
    }
55
56
    /**
57
     * {@inheritdoc}
58
     */
59 40
    public function valueType(): Str
60
    {
61 40
        return $this->valueType;
62
    }
63
64
    /**
65
     * {@inheritdoc}
66
     */
67 38
    public function size(): int
68
    {
69 38
        return $this->size ?? $this->size = \count($this->values);
70
    }
71
72
    /**
73
     * {@inheritdoc}
74
     */
75 2
    public function count(): int
76
    {
77 2
        return $this->size();
78
    }
79
80
    /**
81
     * {@inheritdoc}
82
     */
83 4
    public function current()
84
    {
85 4
        return \current($this->values);
86
    }
87
88
    /**
89
     * {@inheritdoc}
90
     */
91 8
    public function key()
92
    {
93 8
        return $this->normalizeKey(\key($this->values));
94
    }
95
96
    /**
97
     * {@inheritdoc}
98
     */
99 4
    public function next()
100
    {
101 4
        \next($this->values);
102 4
    }
103
104
    /**
105
     * {@inheritdoc}
106
     */
107 100
    public function rewind()
108
    {
109 100
        \reset($this->values);
110 100
    }
111
112
    /**
113
     * {@inheritdoc}
114
     */
115 6
    public function valid()
116
    {
117 6
        return $this->key() !== null;
118
    }
119
120
    /**
121
     * {@inheritdoc}
122
     */
123 58
    public function offsetExists($offset): bool
124
    {
125 58
        return \array_key_exists($offset, $this->values);
126
    }
127
128
    /**
129
     * {@inheritdoc}
130
     */
131 8
    public function offsetGet($offset)
132
    {
133 8
        return $this->get($offset);
134
    }
135
136
    /**
137
     * {@inheritdoc}
138
     */
139 2
    public function offsetSet($offset, $value)
140
    {
141 2
        throw new LogicException('You can\'t modify a map');
142
    }
143
144
    /**
145
     * {@inheritdoc}
146
     */
147 2
    public function offsetUnset($offset)
148
    {
149 2
        throw new LogicException('You can\'t modify a map');
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155 112
    public function put($key, $value): MapInterface
156
    {
157 112
        $this->keySpecification->validate($key);
158 108
        $this->valueSpecification->validate($value);
159
160 100
        $map = clone $this;
161 100
        $map->size = null;
162 100
        $map->values[$key] = $value;
163 100
        $map->rewind();
164
165 100
        return $map;
166
    }
167
168
    /**
169
     * {@inheritdoc}
170
     */
171 48
    public function get($key)
172
    {
173 48
        if (!$this->offsetExists($key)) {
174 8
            throw new ElementNotFoundException;
175
        }
176
177 40
        return $this->values[$key];
178
    }
179
180
    /**
181
     * {@inheritdoc}
182
     */
183 38
    public function contains($key): bool
184
    {
185 38
        return $this->offsetExists($key);
186
    }
187
188
    /**
189
     * {@inheritdoc}
190
     */
191 28
    public function clear(): MapInterface
192
    {
193 28
        $map = clone $this;
194 28
        $map->size = null;
195 28
        $map->values = [];
196
197 28
        return $map;
198
    }
199
200
    /**
201
     * {@inheritdoc}
202
     */
203 14
    public function equals(MapInterface $map): bool
204
    {
205 14
        if ($map->size() !== $this->size()) {
206 4
            return false;
207
        }
208
209 14
        foreach ($this->values as $k => $v) {
210 12
            if (!$map->contains($k)) {
211 4
                return false;
212
            }
213
214 12
            if ($map->get($k) !== $v) {
215 9
                return false;
216
            }
217
        }
218
219 12
        return true;
220
    }
221
222
    /**
223
     * {@inheritdoc}
224
     */
225 4
    public function filter(callable $predicate): MapInterface
226
    {
227 4
        $map = $this->clear();
228
229 4
        foreach ($this->values as $k => $v) {
230 4
            if ($predicate($this->normalizeKey($k), $v) === true) {
231 4
                $map->values[$k] = $v;
232
            }
233
        }
234
235 4
        $map->rewind();
236
237 4
        return $map;
238
    }
239
240
    /**
241
     * {@inheritdoc}
242
     */
243 4
    public function foreach(callable $function): MapInterface
244
    {
245 4
        foreach ($this->values as $k => $v) {
246 4
            $function($this->normalizeKey($k), $v);
247
        }
248
249 4
        return $this;
250
    }
251
252
    /**
253
     * {@inheritdoc}
254
     */
255 8
    public function groupBy(callable $discriminator): MapInterface
256
    {
257 8
        if ($this->size() === 0) {
258 4
            throw new GroupEmptyMapException;
259
        }
260
261 4
        $map = null;
262
263 4
        foreach ($this->values as $k => $v) {
264 4
            $key = $discriminator($this->normalizeKey($k), $v);
265
266 4
            if ($map === null) {
267 4
                $map = new Map(
268 4
                    Type::determine($key),
269 4
                    MapInterface::class
270
                );
271
            }
272
273 4
            if ($map->contains($key)) {
274 4
                $map = $map->put(
275 4
                    $key,
276 4
                    $map->get($key)->put($k, $v)
277
                );
278
            } else {
279 4
                $map = $map->put(
280 4
                    $key,
281 4
                    $this->clear()->put($k, $v)
282
                );
283
            }
284
        }
285
286 4
        return $map;
287
    }
288
289
    /**
290
     * {@inheritdoc}
291
     */
292 28
    public function keys(): SetInterface
293
    {
294 28
        return Set::of(
295 28
            (string) $this->keyType,
296 28
            ...\array_map(function($key) {
297 28
                return $this->normalizeKey($key);
298 28
            }, \array_keys($this->values))
299
        );
300
    }
301
302
    /**
303
     * {@inheritdoc}
304
     */
305 26
    public function values(): StreamInterface
306
    {
307 26
        return Stream::of((string) $this->valueType, ...\array_values($this->values));
308
    }
309
310
    /**
311
     * {@inheritdoc}
312
     */
313 12
    public function map(callable $function): MapInterface
314
    {
315 12
        $map = $this->clear();
316
317 12
        foreach ($this->values as $k => $v) {
318 12
            $return = $function($this->normalizeKey($k), $v);
319
320 12
            if ($return instanceof Pair) {
321 8
                $this->keySpecification->validate($return->key());
322
323 4
                $key = $return->key();
324 4
                $value = $return->value();
325
            } else {
326 8
                $key = $k;
327 8
                $value = $return;
328
            }
329
330 8
            $this->valueSpecification->validate($value);
331
332 4
            $map->values[$key] = $value;
333
        }
334
335 4
        $map->rewind();
336
337 4
        return $map;
338
    }
339
340
    /**
341
     * {@inheritdoc}
342
     */
343 4
    public function join(string $separator): Str
344
    {
345 4
        return $this->values()->join($separator);
346
    }
347
348
    /**
349
     * {@inheritdoc}
350
     */
351 4
    public function remove($key): MapInterface
352
    {
353 4
        if (!$this->contains($key)) {
354 4
            return $this;
355
        }
356
357 4
        $map = clone $this;
358 4
        $map->size = null;
359 4
        unset($map->values[$key]);
360 4
        $map->rewind();
361
362 4
        return $map;
363
    }
364
365
    /**
366
     * {@inheritdoc}
367
     */
368 6
    public function merge(MapInterface $map): MapInterface
369
    {
370
        if (
371 6
            !$this->keyType()->equals($map->keyType()) ||
372 6
            !$this->valueType()->equals($map->valueType())
373
        ) {
374 4
            throw new InvalidArgumentException(
375 4
                'The 2 maps does not reference the same types'
376
            );
377
        }
378
379 2
        return $map->reduce(
380 2
            $this,
381 2
            function(self $carry, $key, $value): self {
382 2
                return $carry->put($key, $value);
383 2
            }
384
        );
385
    }
386
387
    /**
388
     * {@inheritdoc}
389
     */
390 4
    public function partition(callable $predicate): MapInterface
391
    {
392 4
        $truthy = $this->clear();
393 4
        $falsy = $this->clear();
394
395 4
        foreach ($this->values as $k => $v) {
396 4
            $return = $predicate($this->normalizeKey($k), $v);
397
398 4
            if ($return === true) {
399 4
                $truthy->values[$k] = $v;
400
            } else {
401 4
                $falsy->values[$k] = $v;
402
            }
403
        }
404
405 4
        $truthy->rewind();
406 4
        $falsy->rewind();
407
408 4
        return Map::of('bool', MapInterface::class)
409 4
            (true, $truthy)
410 4
            (false, $falsy);
411
    }
412
413
    /**
414
     * {@inheritdoc}
415
     */
416 8
    public function reduce($carry, callable $reducer)
417
    {
418 8
        foreach ($this->values as $k => $v) {
419 8
            $carry = $reducer($carry, $this->normalizeKey($k), $v);
420
        }
421
422 8
        return $carry;
423
    }
424
425 2
    public function empty(): bool
426
    {
427 2
        $this->rewind();
428
429 2
        return !$this->valid();
430
    }
431
432 54
    private function normalizeKey($value)
433
    {
434 54
        if ((string) $this->keyType === 'string') {
435 2
            return (string) $value;
436
        }
437
438 52
        return $value;
439
    }
440
}
441