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.
Completed
Push — develop ( cad621...d8b57f )
by Baptiste
04:31
created

Map::keys()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
declare(strict_types = 1);
3
4
namespace Innmind\Immutable;
5
6
use Innmind\Immutable\{
7
    Exception\InvalidArgumentException,
8
    Exception\LogicException,
9
    Exception\ElementNotFoundException,
10
    Exception\GroupEmptyMapException
11
};
12
13
class Map implements MapInterface
14
{
15
    use Type;
16
17
    private $keyType;
18
    private $valueType;
19
    private $keySpec;
20
    private $valueSpec;
21
    private $keys;
22
    private $values;
23
    private $pairs;
24
25 44
    public function __construct(string $keyType, string $valueType)
26
    {
27 44
        $this->keySpec = $this->getSpecFor($keyType);
28 44
        $this->valueSpec = $this->getSpecFor($valueType);
29 44
        $this->keyType = new StringPrimitive($keyType);
0 ignored issues
show
Deprecated Code introduced by
The class Innmind\Immutable\StringPrimitive has been deprecated with message: To be removed in 2.0

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
30 44
        $this->valueType = new StringPrimitive($valueType);
0 ignored issues
show
Deprecated Code introduced by
The class Innmind\Immutable\StringPrimitive has been deprecated with message: To be removed in 2.0

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
31 44
        $this->keys = new Sequence;
32 44
        $this->values = new Sequence;
33 44
        $this->pairs = new Sequence;
34 44
    }
35
36
    /**
37
     * {@inheritdoc}
38
     */
39 18
    public function keyType(): StringPrimitive
40
    {
41 18
        return $this->keyType;
42
    }
43
44
    /**
45
     * {@inheritdoc}
46
     */
47 17
    public function valueType(): StringPrimitive
48
    {
49 17
        return $this->valueType;
50
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55 11
    public function size(): int
56
    {
57 11
        return $this->keys->size();
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63 2
    public function count(): int
64
    {
65 2
        return $this->keys->count();
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71 1
    public function current()
72
    {
73 1
        return $this->values->current();
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79 1
    public function key()
80
    {
81 1
        return $this->keys->current();
82
    }
83
84
    /**
85
     * {@inheritdoc}
86
     */
87 1
    public function next()
88
    {
89 1
        $this->keys->next();
90 1
        $this->values->next();
91 1
        $this->pairs->next();
92 1
    }
93
94
    /**
95
     * {@inheritdoc}
96
     */
97 1
    public function rewind()
98
    {
99 1
        $this->keys->rewind();
100 1
        $this->values->rewind();
101 1
        $this->pairs->rewind();
102 1
    }
103
104
    /**
105
     * {@inheritdoc}
106
     */
107 1
    public function valid()
108
    {
109 1
        return $this->keys->valid();
110
    }
111
112
    /**
113
     * {@inheritdoc}
114
     */
115 1
    public function offsetExists($offset): bool
116
    {
117 1
        return $this->keys->contains($offset);
118
    }
119
120
    /**
121
     * {@inheritdoc}
122
     */
123 4
    public function offsetGet($offset)
124
    {
125 4
        return $this->get($offset);
126
    }
127
128
    /**
129
     * {@inheritdoc}
130
     */
131 1
    public function offsetSet($offset, $value)
132
    {
133 1
        throw new LogicException('You can\'t modify a map');
134
    }
135
136
    /**
137
     * {@inheritdoc}
138
     */
139 1
    public function offsetUnset($offset)
140
    {
141 1
        throw new LogicException('You can\'t modify a map');
142
    }
143
144
    /**
145
     * {@inheritdoc}
146
     */
147 37
    public function put($key, $value): MapInterface
148
    {
149 37
        $this->keySpec->validate($key);
150 36
        $this->valueSpec->validate($value);
151
152 34
        $map = clone $this;
153
154 34
        if ($this->keys->contains($key)) {
155 7
            $index = $this->keys->indexOf($key);
156 7
            $map->values = (new Sequence)
157 7
                ->append($this->values->take($index))
158 7
                ->add($value)
159 7
                ->append($this->values->drop($index + 1));
160 7
            $map->pairs = (new Sequence)
161 7
                ->append($this->pairs->take($index))
162 7
                ->add(new Pair($key, $value))
163 7
                ->append($this->pairs->drop($index + 1));
164
        } else {
165 34
            $map->keys = $this->keys->add($key);
166 34
            $map->values = $this->values->add($value);
167 34
            $map->pairs = $this->pairs->add(new Pair($key, $value));
168
        }
169
170 34
        return $map;
1 ignored issue
show
Bug Best Practice introduced by
The return type of return $map; (Innmind\Immutable\Map) is incompatible with the return type declared by the interface Innmind\Immutable\MapInterface::put of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
171
    }
172
173
    /**
174
     * {@inheritdoc}
175
     */
176 16
    public function get($key)
177
    {
178 16
        if (!$this->keys->contains($key)) {
179 2
            throw new ElementNotFoundException;
180
        }
181
182 14
        return $this->values->get(
183 14
            $this->keys->indexOf($key)
184
        );
185
    }
186
187
    /**
188
     * {@inheritdoc}
189
     */
190 11
    public function contains($key): bool
191
    {
192 11
        return $this->keys->contains($key);
193
    }
194
195
    /**
196
     * {@inheritdoc}
197
     */
198 1 View Code Duplication
    public function drop(int $size): MapInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
199
    {
200 1
        $map = clone $this;
201 1
        $map->keys = $this->keys->drop($size);
202 1
        $map->values = $this->values->drop($size);
203 1
        $map->pairs = $this->pairs->drop($size);
204
205 1
        return $map;
1 ignored issue
show
Bug Best Practice introduced by
The return type of return $map; (Innmind\Immutable\Map) is incompatible with the return type declared by the interface Innmind\Immutable\MapInterface::drop of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
206
    }
207
208
    /**
209
     * {@inheritdoc}
210
     */
211 1 View Code Duplication
    public function dropEnd(int $size): MapInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
212
    {
213 1
        $map = clone $this;
214 1
        $map->keys = $this->keys->dropEnd($size);
215 1
        $map->values = $this->values->dropEnd($size);
216 1
        $map->pairs = $this->pairs->dropEnd($size);
217
218 1
        return $map;
1 ignored issue
show
Bug Best Practice introduced by
The return type of return $map; (Innmind\Immutable\Map) is incompatible with the return type declared by the interface Innmind\Immutable\MapInterface::dropEnd of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
219
    }
220
221
    /**
222
     * {@inheritdoc}
223
     */
224 6
    public function clear(): MapInterface
225
    {
226 6
        $map = clone $this;
227 6
        $map->keys = new Sequence;
228 6
        $map->values = new Sequence;
229 6
        $map->pairs = new Sequence;
230
231 6
        return $map;
1 ignored issue
show
Bug Best Practice introduced by
The return type of return $map; (Innmind\Immutable\Map) is incompatible with the return type declared by the interface Innmind\Immutable\MapInterface::clear of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
232
    }
233
234
    /**
235
     * {@inheritdoc}
236
     */
237 2
    public function equals(MapInterface $map): bool
238
    {
239 2
        if (!$map->keys()->equals($this->keys())) {
240 2
            return false;
241
        }
242
243 1
        return $map->values()->equals($this->values());
244
    }
245
246
    /**
247
     * {@inheritdoc}
248
     */
249 1
    public function filter(callable $predicate): MapInterface
250
    {
251 1
        $map = $this->clear();
252
253 1
        foreach ($this->pairs as $pair) {
254 1
            if ($predicate($pair->key(), $pair->value()) === true) {
255 1
                $map->keys = $map->keys->add($pair->key());
256 1
                $map->values = $map->values->add($pair->value());
257 1
                $map->pairs = $map->pairs->add($pair);
258
            }
259
        }
260
261 1
        return $map;
262
    }
263
264
    /**
265
     * {@inheritdoc}
266
     */
267
    public function foreach(callable $function): MapInterface
268
    {
269 1
        foreach ($this->pairs as $pair) {
270 1
            $function($pair->key(), $pair->value());
271
        }
272
273 1
        return $this;
1 ignored issue
show
Bug Best Practice introduced by
The return type of return $this; (Innmind\Immutable\Map) is incompatible with the return type declared by the interface Innmind\Immutable\MapInterface::foreach of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
274
    }
275
276
    /**
277
     * {@inheritdoc}
278
     */
279 2 View Code Duplication
    public function groupBy(callable $discriminator): MapInterface
280
    {
281 2
        if ($this->size() === 0) {
282 1
            throw new GroupEmptyMapException;
283
        }
284
285 1
        $map = null;
286
287 1
        foreach ($this->pairs as $pair) {
288 1
            $key = $discriminator($pair->key(), $pair->value());
289
290 1
            if ($map === null) {
291 1
                $type = gettype($key);
292 1
                $map = new self(
293 1
                    $type === 'object' ? get_class($key) : $type,
294 1
                    SequenceInterface::class
295
                );
296
            }
297
298 1
            if ($map->contains($key)) {
299 1
                $map = $map->put(
300
                    $key,
301 1
                    $map->get($key)->add($pair)
302
                );
303
            } else {
304 1
                $map = $map->put($key, new Sequence($pair));
305
            }
306
        }
307
308 1
        return $map;
309
    }
310
311
    /**
312
     * {@inheritdoc}
313
     */
314 1
    public function first(): Pair
315
    {
316 1
        return $this->pairs->first();
317
    }
318
319
    /**
320
     * {@inheritdoc}
321
     */
322 1
    public function last(): Pair
323
    {
324 1
        return $this->pairs->last();
325
    }
326
327
    /**
328
     * {@inheritdoc}
329
     */
330 9
    public function keys(): SequenceInterface
331
    {
332 9
        return $this->keys;
333
    }
334
335
    /**
336
     * {@inheritdoc}
337
     */
338 7
    public function values(): SequenceInterface
339
    {
340 7
        return $this->values;
341
    }
342
343
    /**
344
     * {@inheritdoc}
345
     */
346 3
    public function map(callable $function): MapInterface
347
    {
348 3
        $map = $this->clear();
349
350 3
        foreach ($this->pairs as $pair) {
351 3
            $return = $function(
352 3
                $pair->key(),
353 3
                $pair->value()
354
            );
355
356 3
            if ($return instanceof Pair) {
357 2
                $key = $return->key();
358 2
                $value = $return->value();
359
            } else {
360 2
                $key = $pair->key();
361 2
                $value = $return;
362
            }
363
364 3
            $map = $map->put($key, $value);
365
        }
366
367 1
        return $map;
368
    }
369
370
    /**
371
     * {@inheritdoc}
372
     */
373 1 View Code Duplication
    public function take(int $size): MapInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
374
    {
375 1
        $map = clone $this;
376 1
        $map->keys = $this->keys->take($size);
377 1
        $map->values = $this->values->take($size);
378 1
        $map->pairs = $this->pairs->take($size);
379
380 1
        return $map;
1 ignored issue
show
Bug Best Practice introduced by
The return type of return $map; (Innmind\Immutable\Map) is incompatible with the return type declared by the interface Innmind\Immutable\MapInterface::take of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
381
    }
382
383
    /**
384
     * {@inheritdoc}
385
     */
386 1 View Code Duplication
    public function takeEnd(int $size): MapInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
387
    {
388 1
        $map = clone $this;
389 1
        $map->keys = $this->keys->takeEnd($size);
390 1
        $map->values = $this->values->takeEnd($size);
391 1
        $map->pairs = $this->pairs->takeEnd($size);
392
393 1
        return $map;
1 ignored issue
show
Bug Best Practice introduced by
The return type of return $map; (Innmind\Immutable\Map) is incompatible with the return type declared by the interface Innmind\Immutable\MapInterface::takeEnd of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
394
    }
395
396
    /**
397
     * {@inheritdoc}
398
     */
399 1
    public function join(string $separator): StringPrimitive
400
    {
401 1
        return $this->values->join($separator);
402
    }
403
404
    /**
405
     * {@inheritdoc}
406
     */
407 1
    public function remove($key): MapInterface
408
    {
409 1
        if (!$this->contains($key)) {
410 1
            return $this;
1 ignored issue
show
Bug Best Practice introduced by
The return type of return $this; (Innmind\Immutable\Map) is incompatible with the return type declared by the interface Innmind\Immutable\MapInterface::remove of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
411
        }
412
413 1
        $index = $this->keys->indexOf($key);
414 1
        $map = clone $this;
415 1
        $map->keys = $this
416 1
            ->keys
417 1
            ->slice(0, $index)
418 1
            ->append($this->keys->slice($index + 1, $this->keys->size()));
419 1
        $map->values = $this
420 1
            ->values
421 1
            ->slice(0, $index)
422 1
            ->append($this->values->slice($index + 1, $this->values->size()));
423 1
        $map->pairs = $this
424 1
            ->pairs
425 1
            ->slice(0, $index)
426 1
            ->append($this->pairs->slice($index + 1, $this->pairs->size()));
427
428 1
        return $map;
1 ignored issue
show
Bug Best Practice introduced by
The return type of return $map; (Innmind\Immutable\Map) is incompatible with the return type declared by the interface Innmind\Immutable\MapInterface::remove of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
429
    }
430
431
    /**
432
     * {@inheritdoc}
433
     */
434 2
    public function merge(MapInterface $map): MapInterface
435
    {
436
        if (
437 2
            !$this->keyType()->equals($map->keyType()) ||
438 2
            !$this->valueType()->equals($map->valueType())
439
        ) {
440 1
            throw new InvalidArgumentException(
441 1
                'The 2 maps does not reference the same types'
442
            );
443
        }
444
445 1
        return $map->reduce(
446 1
            clone $this,
447 1
            function(self $carry, $key, $value): self {
448 1
                return $carry->put($key, $value);
449 1
            }
450
        );
451
    }
452
453
    /**
454
     * {@inheritdoc}
455
     */
456 1
    public function partition(callable $predicate): MapInterface
457
    {
458 1
        $truthy = $this->clear();
459 1
        $falsy = $this->clear();
460
461 1
        foreach ($this->pairs as $pair) {
462 1
            $return = $predicate(
463 1
                $pair->key(),
464 1
                $pair->value()
465
            );
466
467 1
            if ($return === true) {
468 1
                $truthy = $truthy->put($pair->key(), $pair->value());
469
            } else {
470 1
                $falsy = $falsy->put($pair->key(), $pair->value());
471
            }
472
        }
473
474 1
        return (new self('bool', MapInterface::class))
475 1
            ->put(true, $truthy)
476 1
            ->put(false, $falsy);
477
    }
478
479
    /**
480
     * {@inheritdoc}
481
     */
482 2
    public function reduce($carry, callable $reducer)
483
    {
484 2
        foreach ($this->pairs as $pair) {
485 2
            $carry = $reducer($carry, $pair->key(), $pair->value());
486
        }
487
488 2
        return $carry;
489
    }
490
}
491