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 — master ( ff3008...d4aa5e )
by Nicholas
03:20
created

FileRepository::yieldByCodepoints()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 8
rs 9.4285
cc 3
eloc 5
nc 3
nop 1
1
<?php
2
3
namespace UCD\Infrastructure\Repository\CharacterRepository;
4
5
use UCD\Unicode\AggregatorRelay;
6
use UCD\Unicode\Character;
7
use UCD\Unicode\Character\Collection;
8
use UCD\Unicode\Character\Properties\General\Block;
9
use UCD\Unicode\Character\Repository;
10
use UCD\Unicode\Character\Repository\CharacterNotFoundException;
11
use UCD\Unicode\Character\WritableRepository;
12
use UCD\Unicode\Codepoint;
13
use UCD\Unicode\CodepointAssigned;
14
15
use UCD\Infrastructure\Repository\CharacterRepository\FileRepository\CharacterSlicer;
16
use UCD\Infrastructure\Repository\CharacterRepository\FileRepository\Property;
17
use UCD\Infrastructure\Repository\CharacterRepository\FileRepository\PropertyAggregators;
18
use UCD\Infrastructure\Repository\CharacterRepository\FileRepository\PropertyFileDirectory;
19
use UCD\Infrastructure\Repository\CharacterRepository\FileRepository\Range;
20
use UCD\Infrastructure\Repository\CharacterRepository\FileRepository\RangeFile;
21
use UCD\Infrastructure\Repository\CharacterRepository\FileRepository\RangeFileDirectory;
22
use UCD\Infrastructure\Repository\CharacterRepository\FileRepository\Serializer;
23
24
class FileRepository implements WritableRepository
25
{
26
    use Repository\Capability\Notify;
27
28
    const DEFAULT_SLICE_SIZE = 1000;
29
30
    /**
31
     * @var RangeFileDirectory
32
     */
33
    private $charactersDirectory;
34
35
    /**
36
     * @var PropertyFileDirectory
37
     */
38
    private $propertiesDirectory;
39
40
    /**
41
     * @var PropertyAggregators|AggregatorRelay[]
42
     */
43
    private $aggregators;
44
45
    /**
46
     * @var Serializer
47
     */
48
    private $serializer;
49
50
    /**
51
     * @var int
52
     */
53
    private $sliceSize;
54
55
    /**
56
     * @param RangeFileDirectory $charactersDirectory
57
     * @param PropertyFileDirectory $propertiesDirectory
58
     * @param PropertyAggregators $aggregators
59
     * @param Serializer $serializer
60
     * @param int $sliceSize
61
     */
62
    public function __construct(
63
        RangeFileDirectory $charactersDirectory,
64
        PropertyFileDirectory $propertiesDirectory,
65
        PropertyAggregators $aggregators,
66
        Serializer $serializer,
67
        $sliceSize = self::DEFAULT_SLICE_SIZE
68
    ) {
69
        $this->charactersDirectory = $charactersDirectory;
70
        $this->serializer = $serializer;
71
        $this->sliceSize = $sliceSize;
72
        $this->propertiesDirectory = $propertiesDirectory;
73
        $this->aggregators = $aggregators;
74
    }
75
76
    /**
77
     * {@inheritDoc}
78
     */
79
    public function getByCodepoint(Codepoint $codepoint)
80
    {
81
        $value = $codepoint->getValue();
82
        $file = $this->getFileByCodepoint($codepoint);
83
        $characters = $file->read();
84
85
        if (!array_key_exists($value, $characters)) {
86
            throw CharacterNotFoundException::withCodepoint($codepoint);
87
        }
88
89
        return $this->serializer->unserialize($characters[$value]);
90
    }
91
92
    /**
93
     * {@inheritDoc}
94
     */
95
    public function getByCodepoints(Codepoint\Collection $codepoints)
96
    {
97
        return new Character\Collection(
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \UCD\Unicode\...depoints($codepoints)); (UCD\Unicode\Character\Collection) is incompatible with the return type declared by the interface UCD\Unicode\Character\Repository::getByCodepoints of type UCD\Unicode\CodepointAssigned[].

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...
98
            $this->yieldByCodepoints($codepoints)
99
        );
100
    }
101
102
    /**
103
     * @param Codepoint\Collection $codepoints
104
     * @return \Generator
105
     */
106
    private function yieldByCodepoints(Codepoint\Collection $codepoints)
107
    {
108
        foreach ($codepoints as $codepoint) {
109
            try {
110
                yield $this->getByCodepoint($codepoint);
111
            } catch (CharacterNotFoundException $e) { }
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
112
        }
113
    }
114
115
    /**
116
     * @param Codepoint $codepoint
117
     * @return RangeFile
118
     * @throws CharacterNotFoundException
119
     */
120
    private function getFileByCodepoint(Codepoint $codepoint)
121
    {
122
        $file = $this->charactersDirectory->getFileFromValue($codepoint->getValue());
123
124
        if ($file === null) {
125
            throw CharacterNotFoundException::withCodepoint($codepoint);
126
        }
127
128
        return $file;
129
    }
130
131
    /**
132
     * {@inheritDoc}
133
     */
134
    public function addMany(Collection $characters)
135
    {
136
        $slices = CharacterSlicer::slice($characters, $this->sliceSize);
137
138
        foreach ($slices as $range => $chunk) {
139
            /** @var Range $range */
140
            $this->createFileWithCharacters($range, $chunk);
141
            $this->addCharactersToAggregators($chunk);
142
            $this->notify();
143
        }
144
145
        $this->writeAggregations();
146
    }
147
148
    /**
149
     * @param Range $range
150
     * @param CodepointAssigned[] $characters
151
     * @return CodepointAssigned[]
152
     */
153
    private function createFileWithCharacters(Range $range, array $characters)
154
    {
155
        $this->charactersDirectory->writeRange(
156
            $range,
157
            $this->flattenCharacters($characters)
158
        );
159
    }
160
161
    /**
162
     * @param CodepointAssigned[] $characters
163
     * @return string[]
164
     */
165
    private function flattenCharacters(array $characters)
166
    {
167
        $flattened = [];
168
169
        foreach ($characters as $character) {
170
            $codepoint = $character->getCodepoint();
171
            $key = $codepoint->getValue();
172
            $flattened[$key] = $this->serializer->serialize($character);;
173
        }
174
175
        return $flattened;
176
    }
177
178
    /**
179
     * @param Codepoint\Range\Collection[] $ranges
180
     * @return string[]
181
     */
182
    public function flattenRanges(array $ranges)
183
    {
184
        $flattened = [];
185
186
        foreach ($ranges as $key => $range) {
187
            $range = $range->toArray();
188
            $flattened[$key] = $this->serializer->serialize($range);
189
        }
190
191
        return $flattened;
192
    }
193
194
    /**
195
     * @param CodepointAssigned[] $characters
196
     */
197
    private function addCharactersToAggregators(array $characters)
198
    {
199
        $this->aggregators->addCharacters($characters);
200
    }
201
202
    /**
203
     * @return bool
204
     */
205
    private function writeAggregations()
206
    {
207
        foreach ($this->aggregators as $property => $aggregator) {
208
            /** @var Property $property */
209
            $ranges = $this->flattenRanges($aggregator->getAllRanges());
210
            $this->propertiesDirectory->writeProperty($property, $ranges);
0 ignored issues
show
Documentation introduced by
$ranges is of type array<integer,string>, but the function expects a array<integer,object<UCD...\FileRepository\Range>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
211
        }
212
    }
213
214
    /**
215
     * {@inheritDoc}
216
     */
217
    public function getAll()
218
    {
219
        return new Collection(
220
            $this->readAll()
221
        );
222
    }
223
224
    /**
225
     * @return \Generator
226
     */
227
    private function readAll()
228
    {
229
        $files = $this->charactersDirectory->getFiles();
230
231
        foreach ($files as $file) {
232
            $characters = $file->read();
233
234
            foreach ($characters as $i => $character) {
235
                yield $i => $this->serializer->unserialize($character);
236
            }
237
        }
238
    }
239
240
    /**
241
     * {@inheritDoc}
242
     */
243
    public function getCodepointsByBlock(Block $block)
244
    {
245
        $property = Property::ofType(Property::BLOCK);
246
        $codepoints = $this->resolveCodepointsByProperty($property, (string)$block);
247
248
        if ($codepoints === null) {
249
            throw Repository\BlockNotFoundException::withBlock($block);
250
        }
251
252
        return Codepoint\Range\Collection::fromArray($codepoints);
253
    }
254
255
    /**
256
     * @param Property $property
257
     * @param string $key
258
     * @return Codepoint\Range[]|null
259
     */
260
    private function resolveCodepointsByProperty(Property $property, $key)
261
    {
262
        $file = $this->propertiesDirectory->getFileForProperty($property);
263
        $map = $file->read();
264
265
        return array_key_exists($key, $map)
266
            ? $this->serializer->unserialize($map[$key])
267
            : null;
268
    }
269
270
    /**
271
     * {@inheritDoc}
272
     */
273
    public function count()
274
    {
275
        $files = $this->charactersDirectory->getFiles();
276
        $tally = 0;
277
278
        foreach ($files as $file) {
279
            $tally += $file->getTotal();
280
        }
281
282
        return $tally;
283
    }
284
}