Passed
Push — latest ( 03f783...d7ba96 )
by Mark
02:37
created

Configuration::configureOptions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
c 1
b 0
f 0
dl 0
loc 9
ccs 8
cts 8
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace UnicornFail\Emoji;
6
7
use Dflydev\DotAccessData\Data;
8
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
9
use Symfony\Component\OptionsResolver\Options;
10
use Symfony\Component\OptionsResolver\OptionsResolver;
11
use UnicornFail\Emoji\Emojibase\DatasetInterface;
12
use UnicornFail\Emoji\Emojibase\ShortcodeInterface;
13
use UnicornFail\Emoji\Exception\InvalidConfigurationException;
14
use UnicornFail\Emoji\Util\Normalize;
15
16
class Configuration extends Data implements ConfigurationInterface
17
{
18
    /**
19
     * @param mixed[]|\Traversable $configuration
20
     */
21 699
    public function __construct(?iterable $configuration = null)
22
    {
23 699
        $resolver = new OptionsResolver();
24 699
        $this->configureOptions($resolver);
25
26 699
        $options = $configuration !== null ? (new \ArrayObject($configuration))->getArrayCopy() : [];
0 ignored issues
show
Bug introduced by
$configuration of type iterable is incompatible with the type array|object expected by parameter $input of ArrayObject::__construct(). ( Ignorable by Annotation )

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

26
        $options = $configuration !== null ? (new \ArrayObject(/** @scrutinizer ignore-type */ $configuration))->getArrayCopy() : [];
Loading history...
27
28
        try {
29 699
            $data = $resolver->resolve($options);
30 18
        } catch (\Throwable $throwable) {
31 18
            throw new InvalidConfigurationException($throwable->getMessage(), (int) $throwable->getCode(), $throwable->getPrevious());
32
        }
33
34 681
        parent::__construct($data);
35 681
    }
36
37
    /**
38
     * @param mixed[]|\Traversable $configuration
39
     */
40 699
    public static function create(?iterable $configuration = null): ConfigurationInterface
41
    {
42 699
        if ($configuration instanceof ConfigurationInterface) {
43 3
            return $configuration;
44
        }
45
46 696
        return new self($configuration);
47
    }
48
49 699
    public function configureOptions(OptionsResolver $resolver): void
50
    {
51 699
        $this->defineConvertEmoticons($resolver);
52 699
        $this->defineExcludeShortcodes($resolver);
53 699
        $this->defineLocale($resolver);
54 699
        $this->defineNative($resolver);
55 699
        $this->definePresentation($resolver);
56 699
        $this->definePreset($resolver);
57 699
        $this->defineStringableType($resolver);
58 699
    }
59
60 699
    protected function defineConvertEmoticons(OptionsResolver $resolver): void
61
    {
62 699
        $resolver->define('convertEmoticons')
63 699
            ->allowedTypes('bool')
64 699
            ->default(true);
65 699
    }
66
67 699
    protected function defineExcludeShortcodes(OptionsResolver $resolver): void
68
    {
69 699
        $resolver->define('excludeShortcodes')
70 699
            ->allowedTypes('string', 'string[]')
71 699
            ->default([])
72 699
            ->normalize(
73
            /**
74
             * @param mixed $value
75
             *
76
             * @return string[]
77
             */
78
                static function (Options $options, $value): array {
79 699
                    if (! $value) {
80 669
                        return $value;
81
                    }
82
83 33
                    return Normalize::shortcodes($value);
84 699
                }
85
            );
86 699
    }
87
88 699
    protected function defineLocale(OptionsResolver $resolver): void
89
    {
90 699
        $resolver->define('locale')
91 699
            ->allowedTypes('string')
92
            ->allowedValues(static function (string $value): bool {
93 699
                return ! ! Normalize::locale($value);
94 699
            })
95 699
            ->default('en')
96
            ->normalize(static function (Options $options, string $value): string {
97 690
                return Normalize::locale($value);
98 699
            });
99 699
    }
100
101 699
    protected function defineNative(OptionsResolver $resolver): void
102
    {
103 699
        $resolver->define('native')
104 699
            ->allowedTypes('bool')
105
            ->default(static function (Options $options): bool {
106 147
                return \in_array($options['locale'], DatasetInterface::NON_LATIN_LOCALES, true);
107 699
            })
108
            ->normalize(static function (Options $options, bool $value) {
109 690
                return $value && \in_array($options['locale'], DatasetInterface::NON_LATIN_LOCALES, true);
110 699
            });
111 699
    }
112
113 699
    protected function definePresentation(OptionsResolver $resolver): void
114
    {
115 699
        $resolver->define('presentation')
116 699
            ->allowedTypes('int', 'null')
117 699
            ->allowedValues(...DatasetInterface::SUPPORTED_PRESENTATIONS)
118 699
            ->default(DatasetInterface::EMOJI);
119 699
    }
120
121 699
    protected function definePreset(OptionsResolver $resolver): void
122
    {
123 699
        $resolver->define('preset')
124 699
            ->allowedTypes('string', 'string[]')
125 699
            ->allowedValues(
126
                /**
127
                 * @param mixed $value
128
                 */
129
                static function ($value): bool {
130 690
                    foreach ((array) $value as $v) {
131 690
                        if (! \in_array($v, ShortcodeInterface::SUPPORTED_PRESETS, true)) {
132 9
                            throw new InvalidOptionsException(\sprintf(
133
                                'The option "preset" with value "%s" is invalid. Accepted values are: %s.',
134 9
                                $v,
135
                                \implode(', ', \array_map(static function ($s) {
136 9
                                    return \sprintf('"%s"', $s);
137 9
                                }, ShortcodeInterface::SUPPORTED_PRESETS))
138
                            ));
139
                        }
140
                    }
141
142 681
                    return true;
143 699
                }
144
            )
145 699
            ->default(ShortcodeInterface::DEFAULT_PRESETS)
146 699
            ->normalize(
147
                /**
148
                 * @param mixed $value
149
                 *
150
                 * @return string[]
151
                 */
152
                static function (Options $options, $value): array {
153
                    // Presets.
154 681
                    $presets = [];
155 681
                    foreach ((array) $value as $preset) {
156 681
                        if (isset(ShortcodeInterface::PRESET_ALIASES[$preset])) {
157 18
                            $presets[] = ShortcodeInterface::PRESET_ALIASES[$preset];
158 663
                        } elseif (isset(ShortcodeInterface::PRESETS[$preset])) {
159 663
                            $presets[] = ShortcodeInterface::PRESETS[$preset];
160
                        }
161
                    }
162
163
                    // Prepend the native preset if local is requires it and enabled.
164 681
                    if ($options['native']) {
165 3
                        \array_unshift($presets, ShortcodeInterface::PRESET_CLDR_NATIVE);
166
                    }
167
168 681
                    return \array_values(\array_unique($presets));
169 699
                }
170
            );
171 699
    }
172
173 699
    protected function defineStringableType(OptionsResolver $resolver): void
174
    {
175 699
        $resolver->define('stringableType')
176 699
            ->allowedTypes('int')
177 699
            ->allowedValues(Lexer::T_EMOTICON, Lexer::T_HTML_ENTITY, Lexer::T_SHORTCODE, Lexer::T_UNICODE)
178 699
            ->default(Lexer::T_UNICODE);
179 699
    }
180
181 72
    public function getIterator(): \ArrayObject
182
    {
183 72
        return new \ArrayObject($this->export());
184
    }
185
}
186