Completed
Branch master (c7b6b7)
by Pierre
19:40 queued 09:38
created

ConfigurableFactory   B

Complexity

Total Complexity 39

Size/Duplication

Total Lines 371
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 371
rs 8.2857
c 0
b 0
f 0
wmc 39

19 Methods

Rating   Name   Duplication   Size   Complexity  
A buildSymbolParser() 0 15 2
A buildFormatParser() 0 5 1
A buildSolar() 0 6 2
A getOptionValue() 0 13 3
A buildConverter() 0 10 1
B buildTime() 0 15 5
A buildSymbolFormatter() 0 10 1
A buildLeapCalculator() 0 16 2
B build() 0 26 1
A buildLexer() 0 3 1
A buildNumberConverter() 0 21 3
A buildMonthes() 0 18 3
A buildFormatter() 0 6 1
A buildAdditionalSymbolParser() 0 18 3
A buildMapper() 0 8 1
A buildLocale() 0 14 2
A buildWeek() 0 20 3
A getOptionValueChoice() 0 18 3
A buildParser() 0 6 1
1
<?php
2
3
namespace Popy\Calendar\Factory;
4
5
use Popy\Calendar\Calendar\ComposedCalendar;
6
use Popy\Calendar\Converter\AgnosticConverter;
7
use Popy\Calendar\Converter\UnixTimeConverter;
8
use Popy\Calendar\Converter\LeapYearCalculator;
9
use Popy\Calendar\Formatter\Localisation;
10
use Popy\Calendar\Formatter\SymbolFormatter;
11
use Popy\Calendar\Formatter\NumberConverter;
12
use Popy\Calendar\Formatter\AgnosticFormatter;
13
use Popy\Calendar\Parser\AgnosticParser;
14
use Popy\Calendar\Parser\ResultMapper;
15
use Popy\Calendar\Parser\FormatLexer;
16
use Popy\Calendar\Parser\FormatParser;
17
use Popy\Calendar\Parser\SymbolParser;
18
19
class ConfigurableFactory
20
{
21
    /**
22
     * Available values for option "leap".
23
     *
24
     * @var array<string>
25
     */
26
    protected $leap = [
27
        'noleap' => LeapYearCalculator\NoLeap::class,
28
        'none'   => LeapYearCalculator\NoLeap::class,
29
        'julian' => LeapYearCalculator\Caesar::class,
30
        'caesar' => LeapYearCalculator\Caesar::class,
31
        'modern'    => LeapYearCalculator\Modern::class,
32
        'gregorian' => LeapYearCalculator\Modern::class,
33
        'futuristic' => LeapYearCalculator\Futuristic::class,
0 ignored issues
show
Bug introduced by
The type Popy\Calendar\Converter\...arCalculator\Futuristic was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
34
        'persian' => LeapYearCalculator\Persian::class,
35
        'hijri'   => LeapYearCalculator\Persian::class,
36
        'von_madler' => LeapYearCalculator\VonMadler::class,
37
        'float' => LeapYearCalculator\FloatBased::class,
38
    ];
39
40
    /**
41
     * Available values for option "locale".
42
     *
43
     * @var array<string>
44
     */
45
    protected $locale = [
46
        'native' => Localisation\NativeHardcoded::class,
47
    ];
48
49
    /**
50
     * Available values for option "month"
51
     *
52
     * @var array<string>
53
     */
54
    protected $month = [
55
        'gregorian' => UnixTimeConverter\GregorianCalendarMonthes::class,
56
        'equal_length' => UnixTimeConverter\EqualLengthMonthes::class,
57
    ];
58
59
    /**
60
     * Available values for option "week"
61
     *
62
     * @var array<string>
63
     */
64
    protected $week = [
65
        'iso' => UnixTimeConverter\Iso8601Weeks::class,
66
        'simple' => UnixTimeConverter\SimpleWeeks::class,
67
    ];
68
69
    /**
70
     * Available values for option "number"
71
     *
72
     * @var array<string>
73
     */
74
    protected $number = [
75
        'two_digits' => NumberConverter\TwoDigitsYear::class,
76
        'roman' => NumberConverter\Roman::class,
77
        'rfc2550' => NumberConverter\RFC2550::class,
78
    ];
79
80
    /**
81
     * Available values for option "additional_symbol_parser"
82
     *
83
     * @var array<string>
84
     */
85
    protected $additional_symbol_parser = [
86
        'none'    => false,
87
        'rfc2550' => SymbolParser\PregNativeRFC2550::class,
88
    ];
89
90
    /**
91
     * Builds a gregorian calendar.
92
     *
93
     * @return ComposedCalendar
94
     */
95
    public function build(array $options = array())
96
    {
97
        $options['leap'] = $this->buildLeapCalculator($options);
98
        $options['locale'] = $this->buildLocale($options);
99
100
        $options['converter'] = $this->buildConverter($options);
101
102
        $options['number_converter'] = $this->buildNumberConverter($options);
103
104
        $options['symbol_formatter'] = $this->buildSymbolFormatter($options);
105
106
        $options['lexer'] = $this->buildLexer($options);
107
108
        $options['formatter'] = $this->buildFormatter($options);
109
110
        $options['mapper'] = $this->buildMapper($options);
111
112
        $options['additional_symbol_parser'] = $this->buildAdditionalSymbolParser($options);
113
114
        $options['symbol_parser'] = $this->buildSymbolParser($options);
115
116
        $options['format_parser'] = $this->buildFormatParser($options);
117
118
        $options['parser'] = $this->buildParser($options);
119
120
        return new ComposedCalendar($options['formatter'], $options['parser']);
121
    }
122
123
    protected function buildLeapCalculator(array &$options)
124
    {
125
        $leap = $this->getOptionValueChoice(
126
            $options,
127
            'leap',
128
            $this->leap,
129
            'modern'
130
        );
131
132
        if (is_object($leap)) {
133
            return $leap;
134
        }
135
136
        return new $leap(
137
            $this->getOptionValue($options, 'year_length', 365),
138
            $this->getOptionValue($options, 'era_start_year', 1970)
139
        );
140
    }
141
142
    protected function buildLocale(array &$options)
143
    {
144
        $locale = $this->getOptionValueChoice(
145
            $options,
146
            'locale',
147
            $this->locale,
148
            'native'
149
        );
150
151
        if (is_object($locale)) {
152
            return $locale;
153
        }
154
155
        return new $locale();
156
    }
157
158
    public function buildConverter(array &$options)
159
    {
160
        return new AgnosticConverter(new UnixTimeConverter\Chain([
161
            new UnixTimeConverter\StandardDateFactory(),
162
            new UnixTimeConverter\Date(),
163
            new UnixTimeConverter\TimeOffset(),
164
            $this->buildSolar($options),
165
            $this->buildMonthes($options),
166
            $this->buildWeek($options),
167
            $this->buildTime($options),
168
        ]));
169
    }
170
171
    protected function buildSolar(array &$options)
172
    {
173
        return new UnixTimeConverter\DateSolar(
174
            $options['leap'],
175
            $this->getOptionValue($options, 'era_start', 0),
176
            $this->getOptionValue($options, 'day_length', false) ?: null
177
        );
178
    }
179
180
    protected function buildMonthes(array &$options)
181
    {
182
        $month = $this->getOptionValueChoice(
183
            $options,
184
            'month',
185
            $this->month,
186
            'gregorian'
187
        );
188
189
        if (is_object($month)) {
190
            return $month;
191
        }
192
193
        if ($month === UnixTimeConverter\EqualLengthMonthes::class) {
194
            return new $month($options['leap'], $this->getOptionValue($options, 'month_length'));
195
        }
196
197
        return new UnixTimeConverter\GregorianCalendarMonthes($options['leap']);
198
    }
199
200
    protected function buildTime(array &$options)
201
    {
202
        $ranges = $this->getOptionValue($options, 'time_ranges', false) ?: null;
203
204
        if ($ranges === 'duodecimal') {
205
            $ranges = null;
206
        }
207
208
        if ($ranges === 'decimal') {
209
            $ranges = [10, 100, 100, 1000, 1000];
210
        }
211
212
        return new UnixTimeConverter\Time(
213
            $ranges,
214
            $this->getOptionValue($options, 'day_length', false) ?: null
215
        );
216
    }
217
218
    protected function buildWeek(array &$options)
219
    {
220
        $week = $this->getOptionValueChoice(
221
            $options,
222
            'week',
223
            $this->week,
224
            'iso'
225
        );
226
227
        if (is_object($week)) {
228
            return $week;
229
        }
230
231
        if ($week === UnixTimeConverter\SimpleWeeks::class) {
232
            return new $week($this->getOptionValue($options, 'week_length'));
233
        }
234
235
        return new UnixTimeConverter\Iso8601Weeks(
236
            $options['leap'],
237
            $this->getOptionValue($options, 'era_start_day_index', 3)
238
        );
239
    }
240
241
    protected function buildNumberConverter(array &$options)
242
    {
243
        $number = $this->getOptionValueChoice(
244
            $options,
245
            'number',
246
            $this->number,
247
            'two_digits'
248
        );
249
250
        if (is_object($number)) {
251
            return $number;
252
        }
253
254
        if ($number === NumberConverter\TwoDigitsYear::class) {
255
            return new $number(
256
                $this->getOptionValue($options, 'number_converter_year', 2000),
257
                $this->getOptionValue($options, 'number_converter_late_fifty', true)
258
            );
259
        }
260
261
        return new $number();
262
    }
263
264
    protected function buildSymbolFormatter(array &$options)
265
    {
266
        return new SymbolFormatter\Chain([
267
            new SymbolFormatter\Litteral(),
268
            new SymbolFormatter\StandardDate(),
269
            new SymbolFormatter\StandardDateFragmented($options['locale']),
270
            new SymbolFormatter\StandardDateSolar($options['number_converter']),
271
            new SymbolFormatter\StandardDateTime(),
272
            new SymbolFormatter\StandardRecursive(),
273
            new SymbolFormatter\Litteral(true),
274
        ]);
275
    }
276
277
    protected function buildLexer(array &$options)
0 ignored issues
show
Unused Code introduced by
The parameter $options is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

277
    protected function buildLexer(/** @scrutinizer ignore-unused */ array &$options)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
278
    {
279
        return new FormatLexer\MbString();
280
    }
281
282
    protected function buildFormatter(array &$options)
283
    {
284
        return new AgnosticFormatter(
285
            $options['lexer'],
286
            $options['converter'],
287
            $options['symbol_formatter']
288
        );
289
    }
290
291
    protected function buildMapper(array &$options)
0 ignored issues
show
Unused Code introduced by
The parameter $options is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

291
    protected function buildMapper(/** @scrutinizer ignore-unused */ array &$options)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
292
    {
293
        return new ResultMapper\Chain([
294
            new ResultMapper\StandardDateFactory(),
295
            new ResultMapper\StandardDate(),
296
            new ResultMapper\StandardDateFragmented(),
297
            new ResultMapper\StandardDateSolar(),
298
            new ResultMapper\StandardDateTime(),
299
        ]);
300
    }
301
302
    protected function buildAdditionalSymbolParser(array &$options)
303
    {
304
        $parser = $this->getOptionValueChoice(
305
            $options,
306
            'additional_symbol_parser',
307
            $this->additional_symbol_parser,
308
            'none'
309
        );
310
311
        if (is_object($parser)) {
312
            return $parser;
313
        }
314
315
        if ($parser === false) {
0 ignored issues
show
introduced by
The condition $parser === false can never be true.
Loading history...
316
            return null;
317
        }
318
319
        return new $parser($options['number_converter']);
320
    }
321
322
    protected function buildSymbolParser(array &$options)
323
    {
324
        $chain = [
325
            new SymbolParser\PregNativeDate(),
326
            new SymbolParser\PregNativeRecursive(),
327
            new SymbolParser\PregNativeDateSolar($options['number_converter']),
328
            new SymbolParser\PregNativeDateFragmented($options['locale']),
329
            new SymbolParser\PregNativeDateTime(),
330
        ];
331
332
        if ($options['additional_symbol_parser']) {
333
            array_unshift($chain, $options['additional_symbol_parser']);
334
        }
335
336
        return new SymbolParser\Chain($chain);
337
    }
338
339
    protected function buildFormatParser(array &$options)
340
    {
341
        return new FormatParser\PregExtendedNative(
342
            $options['lexer'],
343
            $options['symbol_parser']
344
        );
345
    }
346
347
    protected function buildParser(array &$options)
348
    {
349
        return new AgnosticParser(
350
            $options['format_parser'],
351
            $options['mapper'],
352
            $options['converter']
353
        );
354
    }
355
356
    protected function getOptionValue(array $options, $name, $default = null)
357
    {
358
        if (isset($options[$name])) {
359
            return $options[$name];
360
        }
361
362
        if ($default !== null) {
363
            return $default;
364
        }
365
366
        throw new InvalidArgumentException(sprintf(
0 ignored issues
show
Bug introduced by
The type Popy\Calendar\Factory\InvalidArgumentException was not found. Did you mean InvalidArgumentException? If so, make sure to prefix the type with \.
Loading history...
367
            '"%s" option is required.',
368
            $name
369
        ));
370
    }
371
372
    protected function getOptionValueChoice(array $options, $name, $list, $default = null)
373
    {
374
        $value = $this->getOptionValue($options, $name, $default);
375
376
        if (is_object($value)) {
377
            return $value;
378
        }
379
380
        if (!isset($list[$value])) {
381
            throw new InvalidArgumentException(sprintf(
382
                'Invalid value "%s" for option "%s". possible values are : %s',
383
                $value,
384
                $name,
385
                implode(', ', array_keys($list))
386
            ));
387
        }
388
389
        return $list[$value];
390
    }
391
}
392