Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
94.92% covered (success)
94.92%
187 / 197
81.82% covered (success)
81.82%
9 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
SiteHealth
94.92% covered (success)
94.92%
187 / 197
81.82% covered (success)
81.82%
9 / 11
34.15
0.00% covered (danger)
0.00%
0 / 1
 init
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 debugInformation
100.00% covered (success)
100.00%
28 / 28
100.00% covered (success)
100.00%
1 / 1
1
 addContentSettings
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
7
 addProjectSettings
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
1 / 1
1
 addPlayerSettings
100.00% covered (success)
100.00%
50 / 50
100.00% covered (success)
100.00%
1 / 1
5
 addPluginVersion
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
4
 addRestApiConnection
64.00% covered (warning)
64.00%
16 / 25
0.00% covered (danger)
0.00%
0 / 1
2.19
 addFilters
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
5
 addNoticeSettings
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 addConstant
90.00% covered (success)
90.00%
9 / 10
0.00% covered (danger)
0.00%
0 / 1
4.02
 maskString
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3declare(strict_types=1);
4
5/**
6 * BeyondWords SiteHealth.
7 *
8 * @package Beyondwords\Wordpress
9 * @author  Stuart McAlpine <stu@beyondwords.io>
10 * @since   3.7.0
11 */
12
13namespace Beyondwords\Wordpress\Component\SiteHealth;
14
15use Beyondwords\Wordpress\Component\Settings\SettingsUtils;
16use Beyondwords\Wordpress\Core\Environment;
17
18/**
19 * BeyondWords SiteHealth.
20 *
21 * @since 3.7.0
22 */
23class SiteHealth
24{
25    /**
26     * @var string[] List of current filters to check.
27     *
28     * @since  3.7.0 Introduced.
29     * @since  4.3.0 Filters refactoring - many were removed and renamed.
30     */
31    public const FILTERS = [
32        'beyondwords_content_params',
33        'beyondwords_player_script_onload',
34        'beyondwords_player_html',
35        'beyondwords_player_sdk_params',
36        'beyondwords_settings_player_styles',
37        'beyondwords_settings_post_types',
38        'beyondwords_settings_post_statuses',
39    ];
40
41    /**
42     * @var string[] List of deprecated filters to check.
43     *
44     * @since  3.7.0 Introduced.
45     * @since  4.3.0 Filters refactoring - many were removed and renamed.
46     */
47    public const DEPRECATED_FILTERS = [
48        'beyondwords_amp_player_html',
49        'beyondwords_body_params',
50        'beyondwords_content',
51        'beyondwords_content_id',
52        'beyondwords_js_player_html',
53        'beyondwords_js_player_params',
54        'beyondwords_player_styles',
55        'beyondwords_post_audio_enabled_blocks',
56        'beyondwords_post_metadata',
57        'beyondwords_post_player_enabled',
58        'beyondwords_post_statuses',
59        'beyondwords_post_types',
60        'beyondwords_project_id',
61        'sk_player_after',
62        'sk_player_before',
63        'sk_the_content',
64        'speechkit_amp_player_html',
65        'speechkit_content',
66        'speechkit_js_player_html',
67        'speechkit_js_player_params',
68        'speechkit_post_player_enabled',
69        'speechkit_post_statuses',
70        'speechkit_post_types',
71    ];
72
73    /**
74     * Init
75     *
76     * @since 4.0.0
77     */
78    public function init()
79    {
80        add_filter('debug_information', array($this, 'debugInformation'));
81    }
82
83    /**
84     * Add "Site Health" navigation tab.
85     *
86     * @since  3.7.0
87     *
88     * @param array $info
89     *
90     * @return array
91     */
92    public function debugInformation($info)
93    {
94        $info['beyondwords']['label'] = __('BeyondWords - Text-to-Speech', 'speechkit');
95
96        $this->addPluginVersion($info);
97        $this->addRestApiConnection($info);
98
99        $info['beyondwords']['fields']['compatible-post-types'] = [
100            'label' => __('Compatible post types', 'speechkit'),
101            'value' => implode(', ', SettingsUtils::getCompatiblePostTypes()),
102        ];
103
104        $info['beyondwords']['fields']['incompatible-post-types'] = [
105            'label' => __('Incompatible post types', 'speechkit'),
106            'value' => implode(', ', SettingsUtils::getIncompatiblePostTypes()),
107        ];
108
109        $info['beyondwords']['fields']['beyondwords_api_key'] = [
110            'label' => __('API Key', 'speechkit'),
111            'value' => SiteHealth::maskString(get_option('beyondwords_api_key')),
112        ];
113
114        $info['beyondwords']['fields']['beyondwords_project_id'] = [
115            'label' => __('Project ID', 'speechkit'),
116            'value' => get_option('beyondwords_project_id'),
117        ];
118
119        $this->addContentSettings($info);
120        $this->addProjectSettings($info);
121        $this->addPlayerSettings($info);
122        $this->addFilters($info);
123        $this->addNoticeSettings($info);
124
125        $this->addConstant($info, 'BEYONDWORDS_AUTO_SYNC_SETTINGS');
126        $this->addConstant($info, 'BEYONDWORDS_AUTOREGENERATE');
127        $this->addConstant($info, 'BEYONDWORDS_PLAYER_INLINE_SCRIPT_TAG');
128
129        return $info;
130    }
131
132    /**
133     * Add content settings to the info debugging array.
134     *
135     * @since 5.0.0
136     *
137     * @param array $info Debugging info array
138     *
139     * @return array
140     */
141    public function addContentSettings(&$info)
142    {
143        $info['beyondwords']['fields']['beyondwords_project_title_enabled'] = [
144            'label' => __('Include title in audio', 'speechkit'),
145            'value' => get_option('beyondwords_project_title_enabled') ? __('Yes', 'speechkit') : __('No', 'speechkit'), // phpcs:ignore Generic.Files.LineLength.TooLong
146            'debug' => get_option('beyondwords_project_title_enabled') ? 'yes' : 'no',
147        ];
148
149        $info['beyondwords']['fields']['beyondwords_project_auto_publish_enabled'] = [
150            'label' => __('Auto-publish audio', 'speechkit'),
151            'value' => get_option('beyondwords_project_auto_publish_enabled') ? __('Yes', 'speechkit') : __('No', 'speechkit'), // phpcs:ignore Generic.Files.LineLength.TooLong
152            'debug' => get_option('beyondwords_project_auto_publish_enabled') ? 'yes' : 'no',
153        ];
154
155        $info['beyondwords']['fields']['beyondwords_prepend_excerpt'] = [
156            'label' => __('Include excerpts in audio', 'speechkit'),
157            'value' => get_option('beyondwords_prepend_excerpt') ? __('Yes', 'speechkit') : __('No', 'speechkit'), // phpcs:ignore Generic.Files.LineLength.TooLong
158            'debug' => get_option('beyondwords_prepend_excerpt') ? 'yes' : 'no',
159        ];
160
161        $info['beyondwords']['fields']['beyondwords_preselect'] = [
162            'label' => __('Preselect â€˜Generate audio’', 'speechkit'),
163            'value' => (string) wp_json_encode(get_option('beyondwords_preselect'), JSON_PRETTY_PRINT),
164        ];
165    }
166
167    /**
168     * Add project settings to the info debugging array.
169     *
170     * @since 5.0.0
171     *
172     * @param array $info Debugging info array
173     *
174     * @return array
175     */
176    public function addProjectSettings(&$info)
177    {
178        $info['beyondwords']['fields']['beyondwords_project_language_code'] = [
179            'label' => __('Default language code', 'speechkit'),
180            'value' => get_option('beyondwords_project_language_code'),
181        ];
182
183        $info['beyondwords']['fields']['beyondwords_project_language_id'] = [
184            'label' => __('Default language ID', 'speechkit'),
185            'value' => get_option('beyondwords_project_language_id'),
186        ];
187
188        $info['beyondwords']['fields']['beyondwords_project_title_voice_id'] = [
189            'label' => __('Title voice ID', 'speechkit'),
190            'value' => get_option('beyondwords_project_title_voice_id'),
191        ];
192
193        $info['beyondwords']['fields']['beyondwords_project_title_voice_speaking_rate'] = [
194            'label' => __('Title voice speaking rate', 'speechkit'),
195            'value' => get_option('beyondwords_project_title_voice_speaking_rate'),
196        ];
197
198        $info['beyondwords']['fields']['beyondwords_project_body_voice_id'] = [
199            'label' => __('Body voice ID', 'speechkit'),
200            'value' => get_option('beyondwords_project_body_voice_id'),
201        ];
202
203        $info['beyondwords']['fields']['beyondwords_project_body_voice_speaking_rate'] = [
204            'label' => __('Body voice speaking rate', 'speechkit'),
205            'value' => get_option('beyondwords_project_body_voice_speaking_rate'),
206        ];
207    }
208
209    /**
210     * Add player settings to the info debugging array.
211     *
212     * @since 5.0.0
213     *
214     * @param array $info Debugging info array
215     *
216     * @return array
217     */
218    public function addPlayerSettings(&$info)
219    {
220        $info['beyondwords']['fields']['beyondwords_player_ui'] = [
221            'label' => __('Player UI', 'speechkit'),
222            'value' => get_option('beyondwords_player_ui'),
223        ];
224
225        $info['beyondwords']['fields']['beyondwords_player_style'] = [
226            'label' => __('Player style', 'speechkit'),
227            'value' => get_option('beyondwords_player_style'),
228        ];
229
230        $info['beyondwords']['fields']['beyondwords_player_theme'] = [
231            'label' => __('Player theme', 'speechkit'),
232            'value' => get_option('beyondwords_player_theme'),
233        ];
234
235        $info['beyondwords']['fields']['beyondwords_player_theme_light'] = [
236            'label' => __('Light theme', 'speechkit'),
237            'value' => (string) wp_json_encode(get_option('beyondwords_player_theme_light'), JSON_PRETTY_PRINT),
238        ];
239
240        $info['beyondwords']['fields']['beyondwords_player_theme_dark'] = [
241            'label' => __('Dark theme', 'speechkit'),
242            'value' => (string) wp_json_encode(get_option('beyondwords_player_theme_dark'), JSON_PRETTY_PRINT),
243        ];
244
245        $info['beyondwords']['fields']['beyondwords_player_theme_video'] = [
246            'label' => __('Video theme', 'speechkit'),
247            'value' => (string) wp_json_encode(get_option('beyondwords_player_theme_video'), JSON_PRETTY_PRINT),
248        ];
249
250        $info['beyondwords']['fields']['beyondwords_player_call_to_action'] = [
251            'label' => __('Call-to-action', 'speechkit'),
252            'value' => get_option('beyondwords_player_call_to_action'),
253        ];
254
255        $info['beyondwords']['fields']['beyondwords_player_highlight_sections'] = [
256            'label' => __('Text highlighting', 'speechkit'),
257            'value' => get_option('beyondwords_player_highlight_sections') ? __('Yes', 'speechkit') : __('No', 'speechkit'), // phpcs:ignore Generic.Files.LineLength.TooLong
258            'debug' => get_option('beyondwords_player_highlight_sections') ? 'yes' : 'no',
259        ];
260
261        $info['beyondwords']['fields']['beyondwords_player_clickable_sections'] = [
262            'label' => __('Playback from segments', 'speechkit'),
263            'value' => get_option('beyondwords_player_clickable_sections') ? __('Yes', 'speechkit') : __('No', 'speechkit'), // phpcs:ignore Generic.Files.LineLength.TooLong
264            'debug' => get_option('beyondwords_player_clickable_sections') ? 'yes' : 'no',
265        ];
266
267        $info['beyondwords']['fields']['beyondwords_player_widget_style'] = [
268            'label' => __('Widget style', 'speechkit'),
269            'value' => get_option('beyondwords_player_widget_style'),
270        ];
271
272        $info['beyondwords']['fields']['beyondwords_player_widget_position'] = [
273            'label' => __('Widget position', 'speechkit'),
274            'value' => get_option('beyondwords_player_widget_position'),
275        ];
276
277        $info['beyondwords']['fields']['beyondwords_player_skip_button_style'] = [
278            'label' => __('Skip button style', 'speechkit'),
279            'value' => get_option('beyondwords_player_skip_button_style'),
280        ];
281    }
282
283    /**
284     * Add plugin version to the info debugging array.
285     *
286     * @since  3.7.0
287     *
288     * @param array  $info Debugging info array
289     *
290     * @return array
291     */
292    public function addPluginVersion(&$info)
293    {
294        $constVersion = defined('BEYONDWORDS__PLUGIN_VERSION') ? BEYONDWORDS__PLUGIN_VERSION : '';
295        $dbVersion    = get_option('beyondwords_version');
296
297        if ($constVersion && $constVersion === $dbVersion) {
298            $info['beyondwords']['fields']['plugin-version'] = [
299                'label' => __('Plugin version', 'speechkit'),
300                'value' => BEYONDWORDS__PLUGIN_VERSION,
301            ];
302        } else {
303            $info['beyondwords']['fields']['plugin-version'] = [
304                'label' => __('Plugin version', 'speechkit'),
305                'value' => sprintf(
306                    /* translators: 1: Current plugin version, 2: Database plugin version */
307                    __('Version mismatch: file: %1$s / db: %2$s', 'speechkit'),
308                    $constVersion,
309                    $dbVersion
310                ),
311            ];
312        }
313    }
314
315    /**
316     * Adds debugging data for the BeyondWords REST API connection.
317     *
318     * @since 3.7.0
319     * @since 5.2.2 Remove sslverify param for REST API calls.
320     *
321     * @param array  $info Debugging info array
322     *
323     * @return array
324     */
325    public function addRestApiConnection(&$info)
326    {
327        // translators: Tab heading for Site Health navigation.
328        $apiUrl = Environment::getApiUrl();
329
330        $info['beyondwords']['fields']['api-url'] = [
331            'label' => __('REST API URL', 'speechkit'),
332            'value' => $apiUrl,
333        ];
334
335        $response = wp_remote_request(Environment::getApiUrl(), [
336            'blocking'    => true,
337            'body'        => '',
338            'method'      => 'GET',
339        ]);
340
341        if (! is_wp_error($response)) {
342            $info['beyondwords']['fields']['api-communication'] = array(
343                'label' => __('Communication with REST API', 'speechkit'),
344                'value' => __('BeyondWords API is reachable', 'speechkit'),
345                'debug' => 'true',
346            );
347        } else {
348            $info['beyondwords']['fields']['api-communication'] = array(
349                'label' => __('Communication with REST API', 'speechkit'),
350                'value' => sprintf(
351                    /* translators: 1: The IP address the REST API resolves to. 2: The error returned by the lookup. */
352                    __('Unable to reach BeyondWords API at %1$s: %2$s', 'speechkit'),
353                    gethostbyname(Environment::getApiUrl()),
354                    $response->get_error_message()
355                ),
356                'debug' => $response->get_error_message(),
357            );
358        }
359    }
360
361    /**
362     * Adds filters.
363     *
364     * @since 5.0.0
365     *
366     * @param array $info Debugging info array
367     *
368     * @return array
369     */
370    public function addFilters(&$info)
371    {
372        $registered = array_values(array_filter(SiteHealth::FILTERS, 'has_filter'));
373
374        $info['beyondwords']['fields']['registered-filters'] = [
375            'label' => __('Registered filters', 'speechkit'),
376            'value' => empty($registered) ? __('None', 'speechkit') : implode(', ', $registered),
377            'debug' => empty($registered) ? 'none' : implode(', ', $registered),
378        ];
379
380        $registered = array_values(array_filter(SiteHealth::DEPRECATED_FILTERS, 'has_filter'));
381
382        $info['beyondwords']['fields']['registered-deprecated-filters'] = [
383            'label' => __('Registered deprecated filters', 'speechkit'),
384            'value' => empty($registered) ? __('None', 'speechkit') : implode(', ', $registered),
385            'debug' => empty($registered) ? 'none' : implode(', ', $registered),
386        ];
387    }
388
389    /**
390     * Add notice settings to the info debugging array.
391     *
392     * @since 5.4.0
393     *
394     * @param array $info Debugging info array
395     *
396     * @return array
397     */
398    public function addNoticeSettings(&$info)
399    {
400        $info['beyondwords']['fields']['beyondwords_date_activated'] = [
401            'label' => __('Date Activated', 'speechkit'),
402            'value' => get_option('beyondwords_date_activated', ''),
403        ];
404
405        $info['beyondwords']['fields']['beyondwords_notice_review_dismissed'] = [
406            'label' => __('Review Notice Dismissed', 'speechkit'),
407            'value' => get_option('beyondwords_notice_review_dismissed', ''),
408        ];
409    }
410
411    /**
412     * Add a single constant to the debugging info array.
413     *
414     * @since 3.7.0
415     * @since 5.0.0 Handle boolean values.
416     *
417     * @param array  $info Debugging info array
418     * @param string $name Constant name
419     *
420     * @return array
421     */
422    public function addConstant(&$info, $name)
423    {
424        $value = __('Undefined', 'speechkit');
425
426        if (defined($name)) {
427            $value = constant($name);
428
429            if (is_bool($value)) {
430                // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_var_export
431                $value = (true === $value) ? 'True' : 'False';
432            }
433        }
434
435        $info['beyondwords']['fields'][$name] = [
436            'label' => $name,
437            'value' => $value,
438            'debug' => $value,
439        ];
440    }
441
442    /**
443     * Mask a sensitive string for display in Site Health.
444     *
445     * @since  3.7.0
446     * @static
447     *
448     * @param string $string
449     * @param int $count
450     * @param string $char
451     *
452     * @return string
453     */
454    public static function maskString($string, $count = 4, $char = 'X')
455    {
456        if (! is_string($string)) {
457            return '';
458        }
459
460        if (strlen($string) < 8) {
461            return str_repeat($char, strlen($string));
462        } else {
463            return str_repeat($char, strlen($string) - $count) . substr($string, (0 - $count));
464        }
465    }
466}