Test Setup Failed
Pull Request — latest (#3)
by Mark
65:38 queued 30:20
created

Environment::createDefaultConfiguration()   B

Complexity

Conditions 7
Paths 1

Size

Total Lines 128
Code Lines 72

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 72
c 0
b 0
f 0
dl 0
loc 128
rs 7.6775
cc 7
nc 1
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file was originally part of the league/commonmark package.
7
 *
8
 * (c) Colin O'Dell <[email protected]>
9
 *
10
 * Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
11
 *  - (c) John MacFarlane
12
 *
13
 * For the full copyright and license information, please view the LICENSE
14
 * file that was distributed with this source code.
15
 */
16
17
namespace UnicornFail\Emoji\Environment;
18
19
use Dflydev\DotAccessData\Data;
20
use League\Configuration\Configuration;
21
use League\Configuration\ConfigurationBuilderInterface;
22
use League\Configuration\Exception\InvalidConfigurationException;
23
use Nette\Schema\Expect;
24
use UnicornFail\Emoji\Dataset\Dataset;
25
use UnicornFail\Emoji\Dataset\DatasetInterface;
26
use UnicornFail\Emoji\Emojibase\DatasetInterface as EmojibaseDatasetInterface;
27
use UnicornFail\Emoji\Emojibase\ShortcodeInterface;
28
use UnicornFail\Emoji\Exception\LocalePresetException;
29
use UnicornFail\Emoji\Extension\CoreExtension;
30
use UnicornFail\Emoji\Parser\Lexer;
31
use UnicornFail\Emoji\Parser\Parser;
32
use UnicornFail\Emoji\Parser\ParserInterface;
33
use UnicornFail\Emoji\Util\Normalize;
34
35
final class Environment extends AbstractConfigurableEnvironment implements EmojiEnvironmentInterface
36
{
37
    /** @var ?DatasetInterface */
38
    private $dataset;
39
40
    /** @var ?ParserInterface */
41
    private $parser;
42
43
    /**
44
     * @param array<string, mixed> $configuration
45
     */
46
    public static function create(array $configuration = []): self
47
    {
48
        $environment = new self($configuration);
49
50
        foreach (self::defaultExtensions() as $extension) {
51
            $environment->addExtension($extension);
52
        }
53
54
        return $environment;
55
    }
56
57
    public static function createDefaultConfiguration(): ConfigurationBuilderInterface
58
    {
59
        $config = new Configuration();
60
61
        // @todo Figure out a better way to provide context to the normalizing (before) callbacks.
62
        $refConfig     = new \ReflectionObject($config);
63
        $refUserConfig = $refConfig->getProperty('userConfig');
64
        $refUserConfig->setAccessible(true);
65
66
        /** @var Data $userConfig */
67
        $userConfig = $refUserConfig->getValue($config);
68
69
        $config->addSchema(
70
            'convertEmoticons',
71
            Expect::bool(true)
72
        );
73
74
        $config->addSchema(
75
            'exclude',
76
            Expect::structure([
77
                'shortcodes' => Expect::arrayOf('string')
78
                    ->default([])
79
                    ->before(
80
                    /**
81
                     * @param string|string[] $value
82
                     *
83
                     * @return string[]
84
                     */
85
                        static function ($value): array {
86
                            return Normalize::shortcodes($value);
87
                        }
88
                    ),
89
            ])
90
        );
91
92
        $config->addSchema(
93
            'locale',
94
            Expect::anyOf(...EmojibaseDatasetInterface::SUPPORTED_LOCALES)
95
                ->default('en')
96
                ->before(
97
                    static function (string $value): string {
98
                        return Normalize::locale($value);
99
                    }
100
                )
101
        );
102
103
        $config->addSchema(
104
            'native',
105
            Expect::bool()
106
                ->before(
107
                    static function (?bool $value = null) use ($userConfig): bool {
108
                        /** @var string $locale */
109
                        $locale = $userConfig->has('locale')
110
                            ? $userConfig->get('locale')
111
                            : 'en';
112
113
                        $default = \in_array($locale, EmojibaseDatasetInterface::NON_LATIN_LOCALES, true);
114
115
                        if ($value === null) {
116
                            return $default;
117
                        }
118
119
                        $native = $value && $default;
120
121
                        $userConfig->set('native', $native);
122
123
                        return $native;
124
                    }
125
                )
126
        );
127
128
        $config->addSchema(
129
            'presentation',
130
            Expect::anyOf(...EmojibaseDatasetInterface::SUPPORTED_PRESENTATIONS)
131
                ->default(EmojibaseDatasetInterface::EMOJI)
132
        );
133
134
        $config->addSchema(
135
            'preset',
136
            Expect::arrayOf('string')
137
                ->default(ShortcodeInterface::DEFAULT_PRESETS)
138
                ->mergeDefaults(false)
139
                ->before(
140
                /**
141
                 * @param string|string[] $value
142
                 *
143
                 * @return string[]
144
                 */
145
                    static function ($value): array {
146
                        // Presets.
147
                        $presets = [];
148
                        foreach ((array) $value as $preset) {
149
                            if (isset(ShortcodeInterface::PRESET_ALIASES[$preset])) {
150
                                $presets[] = ShortcodeInterface::PRESET_ALIASES[$preset];
151
                            } elseif (isset(ShortcodeInterface::PRESETS[$preset])) {
152
                                $presets[] = ShortcodeInterface::PRESETS[$preset];
153
                            } else {
154
                                throw InvalidConfigurationException::forConfigOption(
155
                                    'preset',
156
                                    $preset,
157
                                    \sprintf(
158
                                        'Accepted values are: %s.',
159
                                        \implode(
160
                                            ', ',
161
                                            \array_map(
162
                                                static function ($s) {
163
                                                    return \sprintf('"%s"', $s);
164
                                                },
165
                                                ShortcodeInterface::SUPPORTED_PRESETS
166
                                            )
167
                                        )
168
                                    )
169
                                );
170
                            }
171
                        }
172
173
                        return \array_values(\array_unique($presets));
174
                    }
175
                )
176
        );
177
178
        $config->addSchema(
179
            'stringableType',
180
            Expect::anyOf(Lexer::EMOTICON, Lexer::HTML_ENTITY, Lexer::SHORTCODE, Lexer::UNICODE)
181
                ->default(Lexer::UNICODE)
182
        );
183
184
        return $config;
185
    }
186
187
    /**
188
     * {@inheritDoc}
189
     */
190
    protected static function defaultExtensions(): iterable
191
    {
192
        return [new CoreExtension()];
193
    }
194
195
    /**
196
     * @param string[] $presets
197
     */
198
    protected static function loadLocalePreset(
199
        string $locale = 'en',
200
        array $presets = ShortcodeInterface::DEFAULT_PRESETS
201
    ): DatasetInterface {
202
        $throwables = [];
203
        $presets    = \array_filter($presets);
204
        $remaining  = $presets;
205
        while (\count($remaining) > 0) {
206
            $preset = \array_shift($remaining);
207
            try {
208
                return Dataset::unarchive(\sprintf('%s/%s/%s.gz', DatasetInterface::DIRECTORY, $locale, $preset));
209
            } catch (\Throwable $throwable) {
210
                $throwables[$preset] = $throwable;
211
            }
212
        }
213
214
        throw new LocalePresetException($locale, $throwables);
215
    }
216
217
    public function getDataset(): DatasetInterface
218
    {
219
        if ($this->dataset === null) {
220
            $config = $this->getConfiguration();
221
            $locale = $config->get('locale');
222
            \assert(\is_string($locale));
223
224
            /** @var string[] $presets */
225
            $presets = $config->get('preset');
226
227
            // Prepend the native preset if local is requires it and enabled.
228
            if ($config->get('native')) {
229
                \array_unshift($presets, ShortcodeInterface::PRESET_CLDR_NATIVE);
230
            }
231
232
            $this->dataset = self::loadLocalePreset($locale, $presets);
233
        }
234
235
        return $this->dataset;
236
    }
237
238
    public function getParser(): ParserInterface
239
    {
240
        if ($this->parser === null) {
241
            $this->parser = new Parser($this);
242
        }
243
244
        return $this->parser;
245
    }
246
247
    public function setDataset(DatasetInterface $dataset): void
248
    {
249
        $this->dataset = $dataset;
250
    }
251
252
    public function setParser(ParserInterface $parser): void
253
    {
254
        $this->parser = $parser;
255
    }
256
}
257