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 ( 0edef5...fd3de2 )
by Nicholas
03:23
created

FileRepository::getCodepointsByScript()   A

Complexity

Conditions 1
Paths 1

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 1
eloc 5
nc 1
nop 1
1
<?php
2
3
namespace UCD\Infrastructure\Repository\CharacterRepository;
4
5
use UCD\Exception;
6
use UCD\Unicode\Character;
7
use UCD\Unicode\Character\Collection;
8
use UCD\Unicode\Character\Properties;
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\Codepoint\AggregatorRelay;
14
use UCD\Unicode\CodepointAssigned;
15
16
use UCD\Infrastructure\Repository\CharacterRepository\FileRepository\CharacterSlicer;
17
use UCD\Infrastructure\Repository\CharacterRepository\FileRepository\Property;
18
use UCD\Infrastructure\Repository\CharacterRepository\FileRepository\PropertyAggregators;
19
use UCD\Infrastructure\Repository\CharacterRepository\FileRepository\PropertyFileDirectory;
20
use UCD\Infrastructure\Repository\CharacterRepository\FileRepository\Range;
21
use UCD\Infrastructure\Repository\CharacterRepository\FileRepository\RangeFile;
22
use UCD\Infrastructure\Repository\CharacterRepository\FileRepository\RangeFileDirectory;
23
use UCD\Infrastructure\Repository\CharacterRepository\FileRepository\Serializer;
24
25
class FileRepository implements WritableRepository
26
{
27
    use Repository\Capability\Notify;
28
29
    const DEFAULT_SLICE_SIZE = 1000;
30
31
    /**
32
     * @var RangeFileDirectory
33
     */
34
    private $charactersDirectory;
35
36
    /**
37
     * @var PropertyFileDirectory
38
     */
39
    private $propertiesDirectory;
40
41
    /**
42
     * @var PropertyAggregators|AggregatorRelay[]
43
     */
44
    private $aggregators;
45
46
    /**
47
     * @var Serializer
48
     */
49
    private $serializer;
50
51
    /**
52
     * @var int
53
     */
54
    private $sliceSize;
55
56
    /**
57
     * @param RangeFileDirectory $charactersDirectory
58
     * @param PropertyFileDirectory $propertiesDirectory
59
     * @param PropertyAggregators $aggregators
60
     * @param Serializer $serializer
61
     * @param int $sliceSize
62
     */
63
    public function __construct(
64
        RangeFileDirectory $charactersDirectory,
65
        PropertyFileDirectory $propertiesDirectory,
66
        PropertyAggregators $aggregators,
67
        Serializer $serializer,
68
        $sliceSize = self::DEFAULT_SLICE_SIZE
69
    ) {
70
        $this->charactersDirectory = $charactersDirectory;
71
        $this->serializer = $serializer;
72
        $this->sliceSize = $sliceSize;
73
        $this->propertiesDirectory = $propertiesDirectory;
74
        $this->aggregators = $aggregators;
75
    }
76
77
    /**
78
     * {@inheritDoc}
79
     */
80
    public function getByCodepoint(Codepoint $codepoint)
81
    {
82
        $value = $codepoint->getValue();
83
        $file = $this->getFileByCodepoint($codepoint);
84
        $characters = $file->read();
85
86
        if (!array_key_exists($value, $characters)) {
87
            throw CharacterNotFoundException::withCodepoint($codepoint);
88
        }
89
90
        return $this->serializer->unserialize($characters[$value]);
91
    }
92
93
    /**
94
     * {@inheritDoc}
95
     */
96
    public function getByCodepoints(Codepoint\Collection $codepoints)
97
    {
98
        return new Character\Collection(
99
            $this->yieldByCodepoints($codepoints)
100
        );
101
    }
102
103
    /**
104
     * @param Codepoint\Collection $codepoints
105
     * @return \Generator
106
     */
107
    private function yieldByCodepoints(Codepoint\Collection $codepoints)
108
    {
109
        foreach ($codepoints as $codepoint) {
110
            try {
111
                yield $this->getByCodepoint($codepoint);
112
            } catch (CharacterNotFoundException $e) {
113
                // Missing characters are skipped
114
            }
115
        }
116
    }
117
118
    /**
119
     * @param Codepoint $codepoint
120
     * @return RangeFile
121
     * @throws CharacterNotFoundException
122
     */
123
    private function getFileByCodepoint(Codepoint $codepoint)
124
    {
125
        $file = $this->charactersDirectory->getFileFromValue($codepoint->getValue());
126
127
        if ($file === null) {
128
            throw CharacterNotFoundException::withCodepoint($codepoint);
129
        }
130
131
        return $file;
132
    }
133
134
    /**
135
     * {@inheritDoc}
136
     */
137
    public function addMany(Collection $characters)
138
    {
139
        $slices = CharacterSlicer::slice($characters, $this->sliceSize);
140
141
        foreach ($slices as $range => $chunk) {
142
            /** @var Range $range */
143
            $this->createFileWithCharacters($range, $chunk);
144
            $this->addCharactersToAggregators($chunk);
145
            $this->notify();
146
        }
147
148
        $this->writeAggregations();
149
    }
150
151
    /**
152
     * @param Range $range
153
     * @param CodepointAssigned[] $characters
154
     * @return CodepointAssigned[]
155
     */
156
    private function createFileWithCharacters(Range $range, array $characters)
157
    {
158
        $this->charactersDirectory->writeRange(
159
            $range,
160
            $this->flattenCharacters($characters)
161
        );
162
    }
163
164
    /**
165
     * @param CodepointAssigned[] $characters
166
     * @return string[]
167
     */
168
    private function flattenCharacters(array $characters)
169
    {
170
        $flattened = [];
171
172
        foreach ($characters as $character) {
173
            $codepoint = $character->getCodepoint();
174
            $key = $codepoint->getValue();
175
            $flattened[$key] = $this->serializer->serialize($character);;
176
        }
177
178
        return $flattened;
179
    }
180
181
    /**
182
     * @param Codepoint\Range\Collection[] $ranges
183
     * @return string[]
184
     */
185
    public function flattenRanges(array $ranges)
186
    {
187
        $flattened = [];
188
189
        foreach ($ranges as $key => $range) {
190
            $range = $range->toArray();
191
            $flattened[$key] = $this->serializer->serialize($range);
192
        }
193
194
        return $flattened;
195
    }
196
197
    /**
198
     * @param CodepointAssigned[] $characters
199
     */
200
    private function addCharactersToAggregators(array $characters)
201
    {
202
        $this->aggregators->addCharacters($characters);
203
    }
204
205
    /**
206
     * @return bool
207
     */
208
    private function writeAggregations()
209
    {
210
        foreach ($this->aggregators as $property => $aggregator) {
211
            /** @var Property $property */
212
            $ranges = $this->flattenRanges($aggregator->getAllRanges());
213
            $this->propertiesDirectory->writeProperty($property, $ranges);
214
        }
215
    }
216
217
    /**
218
     * {@inheritDoc}
219
     */
220
    public function getAll()
221
    {
222
        return new Collection(
223
            $this->readAll()
224
        );
225
    }
226
227
    /**
228
     * @return \Generator
229
     */
230
    private function readAll()
231
    {
232
        $files = $this->charactersDirectory->getFiles();
233
234
        foreach ($files as $file) {
235
            $characters = $file->read();
236
237
            foreach ($characters as $i => $character) {
238
                yield $i => $this->serializer->unserialize($character);
239
            }
240
        }
241
    }
242
243
    /**
244
     * {@inheritDoc}
245
     */
246
    public function getCodepointsByBlock(Properties\General\Block $block)
247
    {
248
        return $this->resolveCodepointsByProperty(
249
            Property::ofType(Property::BLOCK),
250
            (string)$block,
251
            Repository\BlockNotFoundException::withBlock($block)
252
        );
253
    }
254
255
    /**
256
     * {@inheritDoc}
257
     */
258
    public function getCodepointsByCategory(Properties\General\GeneralCategory $category)
259
    {
260
        return $this->resolveCodepointsByProperty(
261
            Property::ofType(Property::GENERAL_CATEGORY),
262
            (string)$category,
263
            Repository\GeneralCategoryNotFoundException::withCategory($category)
264
        );
265
    }
266
267
    /**
268
     * {@inheritDoc}
269
     */
270
    public function getCodepointsByScript(Properties\General\Script $script)
271
    {
272
        return $this->resolveCodepointsByProperty(
273
            Property::ofType(Property::SCRIPT),
274
            (string)$script,
275
            Repository\ScriptNotFoundException::withScript($script)
276
        );
277
    }
278
279
    /**
280
     * @param Property $property
281
     * @param string $key
282
     * @param Exception $notFoundException
283
     * @return Codepoint\Range[]
284
     * @throws Exception
285
     */
286
    private function resolveCodepointsByProperty(Property $property, $key, Exception $notFoundException)
287
    {
288
        $file = $this->propertiesDirectory->getFileForProperty($property);
289
        $map = $file->read();
290
291
        $codepoints = array_key_exists($key, $map)
292
            ? $this->serializer->unserialize($map[$key])
293
            : [];
294
295
        if (count($codepoints) === 0) {
296
            throw $notFoundException;
297
        }
298
299
        return Codepoint\Range\Collection::fromArray($codepoints);
300
    }
301
302
    /**
303
     * {@inheritDoc}
304
     */
305
    public function count()
306
    {
307
        $files = $this->charactersDirectory->getFiles();
308
        $tally = 0;
309
310
        foreach ($files as $file) {
311
            $tally += $file->getTotal();
312
        }
313
314
        return $tally;
315
    }
316
}