Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.18% covered (success)
95.18%
158 / 166
88.89% covered (success)
88.89%
8 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
PlayerColors
95.15% covered (success)
95.15%
157 / 165
88.89% covered (success)
88.89%
8 / 9
19
0.00% covered (danger)
0.00%
0 / 1
 init
55.56% covered (danger)
55.56%
10 / 18
0.00% covered (danger)
0.00%
0 / 1
1.09
 addPlayerThemeSetting
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
1
 addPlayerColorsSetting
100.00% covered (success)
100.00%
45 / 45
100.00% covered (success)
100.00%
1 / 1
1
 renderPlayerThemeSetting
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
2
 sanitizeColorsArray
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
6
 sanitizeColor
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getPlayerThemeOptions
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
1
 renderPlayerColorsSetting
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
1
 playerColorsTable
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2
3declare(strict_types=1);
4
5/**
6 * Setting: Player colors
7 *
8 * @package Beyondwords\Wordpress
9 * @author  Stuart McAlpine <stu@beyondwords.io>
10 * @since   5.0.0
11 */
12
13namespace Beyondwords\Wordpress\Component\Settings\Fields\PlayerColors;
14
15use Beyondwords\Wordpress\Component\Settings\SettingsUtils;
16use Beyondwords\Wordpress\Component\Settings\Sync;
17
18/**
19 * PlayerColors
20 *
21 * @since 5.0.0
22 */
23defined('ABSPATH') || exit;
24
25class PlayerColors
26{
27    /**
28     * Option name.
29     */
30    public const OPTION_NAME_THEME = 'beyondwords_player_theme';
31
32    /**
33     * Option name.
34     */
35    public const OPTION_NAME_LIGHT_THEME = 'beyondwords_player_theme_light';
36
37    /**
38     * Option name.
39     */
40    public const OPTION_NAME_DARK_THEME = 'beyondwords_player_theme_dark';
41
42    /**
43     * Option name.
44     */
45    public const OPTION_NAME_VIDEO_THEME = 'beyondwords_player_theme_video';
46
47    /**
48     * Init.
49     *
50     * @since 5.0.0
51     * @since 6.0.0 Make static.
52     */
53    public static function init()
54    {
55        add_action('admin_init', [self::class, 'addPlayerThemeSetting']);
56        add_action('admin_init', [self::class, 'addPlayerColorsSetting']);
57        add_action('pre_update_option_' . self::OPTION_NAME_THEME, function ($value) {
58            Sync::syncOptionToDashboard(self::OPTION_NAME_THEME);
59            return $value;
60        });
61        add_action('pre_update_option_' . self::OPTION_NAME_LIGHT_THEME, function ($value) {
62            Sync::syncOptionToDashboard(self::OPTION_NAME_LIGHT_THEME);
63            return $value;
64        });
65        add_action('pre_update_option_' . self::OPTION_NAME_DARK_THEME, function ($value) {
66            Sync::syncOptionToDashboard(self::OPTION_NAME_DARK_THEME);
67            return $value;
68        });
69        add_action('pre_update_option_' . self::OPTION_NAME_VIDEO_THEME, function ($value) {
70            Sync::syncOptionToDashboard(self::OPTION_NAME_VIDEO_THEME);
71            return $value;
72        });
73    }
74
75    /**
76     * Init "Player color" setting.
77     *
78     * @since 5.0.0
79     * @since 6.0.0 Make static.
80     *
81     * @return void
82     */
83    public static function addPlayerThemeSetting()
84    {
85        register_setting(
86            'beyondwords_player_settings',
87            self::OPTION_NAME_THEME,
88            [
89                'default' => '',
90            ]
91        );
92
93        add_settings_field(
94            'beyondwords-player-theme',
95            __('Player theme', 'speechkit'),
96            [self::class, 'renderPlayerThemeSetting'],
97            'beyondwords_player',
98            'styling'
99        );
100    }
101
102    /**
103     * Init "Player colors" setting.
104     *
105     * @since 5.0.0
106     * @since 6.0.0 Make static.
107     *
108     * @return void
109     */
110    public static function addPlayerColorsSetting()
111    {
112        register_setting(
113            'beyondwords_player_settings',
114            self::OPTION_NAME_LIGHT_THEME,
115            [
116                'default' => [
117                    'background_color' => '#f5f5f5',
118                    'icon_color'       => '#000',
119                    'text_color'       => '#111',
120                    'highlight_color'  => '#eee',
121                ],
122                'sanitize_callback' => [self::class, 'sanitizeColorsArray'],
123            ]
124        );
125
126        register_setting(
127            'beyondwords_player_settings',
128            self::OPTION_NAME_DARK_THEME,
129            [
130                'default' => [
131                    'background_color' => '#f5f5f5',
132                    'icon_color'       => '#000',
133                    'text_color'       => '#111',
134                    'highlight_color'  => '#eee',
135                ],
136                'sanitize_callback' => [self::class, 'sanitizeColorsArray'],
137            ]
138        );
139
140        register_setting(
141            'beyondwords_player_settings',
142            self::OPTION_NAME_VIDEO_THEME,
143            [
144                'default' => [
145                    'background_color' => '#000',
146                    'icon_color'       => '#fff',
147                    'text_color'       => '#fff',
148                ],
149                'sanitize_callback' => [self::class, 'sanitizeColorsArray'],
150            ]
151        );
152
153        add_settings_field(
154            'beyondwords-player-colors',
155            __('Player colors', 'speechkit'),
156            [self::class, 'renderPlayerColorsSetting'],
157            'beyondwords_player',
158            'styling'
159        );
160    }
161
162    /**
163     * Render setting field.
164     *
165     * @since 5.0.0
166     * @since 6.0.0 Make static.
167     *
168     * @return string
169     **/
170    public static function renderPlayerThemeSetting()
171    {
172        $current = get_option(self::OPTION_NAME_THEME);
173        $themeOptions = self::getPlayerThemeOptions();
174        ?>
175        <div class="beyondwords-setting__player beyondwords-setting__player--player-colors">
176            <select name="<?php echo esc_attr(self::OPTION_NAME_THEME) ?>">
177                <?php
178                foreach ($themeOptions as $option) {
179                    printf(
180                        '<option value="%s" %s>%s</option>',
181                        esc_attr($option['value']),
182                        selected($option['value'], $current),
183                        esc_html($option['label'])
184                    );
185                }
186                ?>
187            </select>
188        </div>
189        <?php
190    }
191
192    /**
193     * Sanitise the colors array setting value.
194     *
195     * @since 5.0.0
196     * @since 6.0.0 Make static.
197     *
198     * @param array $value The submitted value.
199     *
200     * @return array The sanitized value.
201     **/
202    public static function sanitizeColorsArray($value)
203    {
204        if (!is_array($value)) {
205            return [];
206        }
207
208        $value['background_color'] = self::sanitizeColor($value['background_color'] ?: '');
209        $value['text_color']       = self::sanitizeColor($value['text_color']       ?: '');
210        $value['icon_color']       = self::sanitizeColor($value['icon_color']       ?: '');
211
212        // Highlight doesn't exist for video player
213        if (!empty($value['highlight_color'])) {
214            $value['highlight_color'] = self::sanitizeColor($value['highlight_color']);
215        }
216
217        return $value;
218    }
219
220    /**
221     * Sanitize an individual color value.
222     *
223     * @since 5.0.0
224     * @since 6.0.0 Make static.
225     *
226     * @param string $value The submitted individual color value.
227     *
228     * @return array The sanitized value.
229     **/
230    public static function sanitizeColor($value)
231    {
232        $value = strtolower(trim((string)$value));
233
234        // Prepend hash to hexidecimal values, if missing
235        if (preg_match("/^[0-9a-f]+$/", $value)) {
236            $value = '#' . $value;
237        }
238
239        return $value;
240    }
241
242    /**
243     * Get all options for the current component.
244     *
245     * @since 5.0.0
246     * @since 6.0.0 Make static.
247     *
248     * @return string[] Associative array of player theme options.
249     **/
250    public static function getPlayerThemeOptions()
251    {
252        return [
253            [
254                'value' => 'light',
255                'label' => 'Light (default)',
256            ],
257            [
258                'value' => 'dark',
259                'label' => 'Dark',
260            ],
261            [
262                'value' => 'auto',
263                'label' => 'Auto',
264            ],
265        ];
266    }
267
268    /**
269     * Render setting field.
270     *
271     * @since 5.0.0
272     * @since 6.0.0 Make static.
273     *
274     * @return string
275     **/
276    public static function renderPlayerColorsSetting()
277    {
278        $lightTheme = get_option(self::OPTION_NAME_LIGHT_THEME);
279        $darkTheme  = get_option(self::OPTION_NAME_DARK_THEME);
280        $videoTheme = get_option(self::OPTION_NAME_VIDEO_THEME);
281
282        self::playerColorsTable(
283            __('Light theme settings', 'speechkit'),
284            self::OPTION_NAME_LIGHT_THEME,
285            $lightTheme,
286        );
287
288        self::playerColorsTable(
289            __('Dark theme settings', 'speechkit'),
290            self::OPTION_NAME_DARK_THEME,
291            $darkTheme,
292        );
293
294        self::playerColorsTable(
295            __('Video theme settings', 'speechkit'),
296            self::OPTION_NAME_VIDEO_THEME,
297            $videoTheme,
298        );
299    }
300
301    /**
302     * A player colors table.
303     *
304     * @since 5.0.0
305     * @since 6.0.0 Make static.
306     *
307     * @return string
308     **/
309    public static function playerColorsTable($title, $name, $value)
310    {
311        ?>
312        <h3 class="subheading">
313            <?php echo esc_html($title); ?>
314        </h3>
315        <div class="color-pickers">
316            <div class="row">
317                <?php
318                SettingsUtils::colorInput(
319                    __('Background', 'speechkit'),
320                    sprintf('%s[background_color]', $name),
321                    $value['background_color'] ?: ''
322                );
323                ?>
324            </div>
325            <div class="row">
326                <?php
327                SettingsUtils::colorInput(
328                    __('Icons', 'speechkit'),
329                    sprintf('%s[icon_color]', $name),
330                    $value['icon_color'] ?: ''
331                );
332                ?>
333            </div>
334            <div class="row">
335                <?php
336                SettingsUtils::colorInput(
337                    __('Text color', 'speechkit'),
338                    sprintf('%s[text_color]', $name),
339                    $value['text_color'] ?: ''
340                );
341                ?>
342            </div>
343        </div>
344        <?php
345    }
346}