Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
83.76% covered (success)
83.76%
98 / 117
55.56% covered (danger)
55.56%
5 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
PreselectGenerateAudio
83.62% covered (success)
83.62%
97 / 116
55.56% covered (danger)
55.56%
5 / 9
32.70
0.00% covered (danger)
0.00%
0 / 1
 init
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 addSetting
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
1
 render
64.00% covered (warning)
64.00%
16 / 25
0.00% covered (danger)
0.00%
0 / 1
3.42
 renderTaxonomyFields
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
5
 renderTaxonomyTerms
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
1 / 1
3
 postTypeIsSelected
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
3.14
 taxonomyIsSelected
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
20
 termIsSelected
62.50% covered (warning)
62.50%
5 / 8
0.00% covered (danger)
0.00%
0 / 1
7.90
 enqueueScripts
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3declare(strict_types=1);
4
5/**
6 * Setting: PreselectGenerateAudio
7 *
8 * @package Beyondwords\Wordpress
9 * @author  Stuart McAlpine <stu@beyondwords.io>
10 * @since   3.0.0
11 */
12
13namespace Beyondwords\Wordpress\Component\Settings\Fields\PreselectGenerateAudio;
14
15use Beyondwords\Wordpress\Component\Settings\SettingsUtils;
16
17/**
18 * PreselectGenerateAudio
19 *
20 * @since 3.0.0
21 */
22defined('ABSPATH') || exit;
23
24class PreselectGenerateAudio
25{
26    /**
27     * Option name.
28     *
29     * @since 5.0.0
30     */
31    public const OPTION_NAME = 'beyondwords_preselect';
32
33    public const DEFAULT_PRESELECT = [
34        'post' => '1',
35        'page' => '1',
36    ];
37
38    /**
39     * Init.
40     *
41     * @since 4.0.0
42     * @since 6.0.0 Make static.
43     */
44    public static function init()
45    {
46        add_action('admin_init', [self::class, 'addSetting']);
47        add_action('admin_enqueue_scripts', [self::class, 'enqueueScripts']);
48    }
49
50    /**
51     * Init setting.
52     *
53     * @since 5.0.0
54     * @since 6.0.0 Make static.
55     *
56     * @return void
57     */
58    public static function addSetting()
59    {
60        register_setting(
61            'beyondwords_content_settings',
62            self::OPTION_NAME,
63            [
64                'default' => self::DEFAULT_PRESELECT,
65            ]
66        );
67
68        add_settings_field(
69            'beyondwords-preselect',
70            __('Preselect ‘Generate audio’', 'speechkit'),
71            [self::class, 'render'],
72            'beyondwords_content',
73            'content'
74        );
75    }
76
77    /**
78     * Render setting field.
79     *
80     * @since 3.0.0
81     * @since 6.0.0 Make static.
82     *
83     * @return void
84     **/
85    public static function render()
86    {
87        $postTypes = SettingsUtils::getCompatiblePostTypes();
88
89        if (count($postTypes) === 0) :
90            ?>
91            <p class="description">
92                <?php
93                esc_html_e(
94                    'No compatible post types found. This plugin will only work with post types that support custom fields.', // phpcs:ignore Generic.Files.LineLength.TooLong
95                    'speechkit'
96                );
97                ?>
98            </p>
99            <?php
100            return;
101        endif;
102
103        foreach ($postTypes as $name) :
104            $postType = get_post_type_object($name);
105            ?>
106            <div class="beyondwords-setting__preselect--post-type">
107                <label>
108                    <input
109                        type="checkbox"
110                        name="<?php echo esc_attr(self::OPTION_NAME); ?>[<?php echo esc_attr($postType->name); ?>]"
111                        value="1"
112                        <?php checked(self::postTypeIsSelected($postType)); ?>
113                    />
114                    <?php echo esc_html($postType->label); ?>
115                </label>
116                <?php self::renderTaxonomyFields($postType); ?>
117            </div>
118            <?php
119        endforeach;
120    }
121
122    /**
123     * Get the taxonomy fields, as a hierarchical list of nested checkboxes.
124     *
125     * @since 3.0.0
126     * @since 6.0.0 Make static.
127     *
128     * @return void
129     **/
130    public static function renderTaxonomyFields($postType)
131    {
132        $taxonomies = get_object_taxonomies($postType->name, 'objects');
133
134        if ($taxonomies) {
135            ?>
136            <div class="beyondwords-setting__preselect--taxonomy" style="margin: 0.5rem 0;">
137                <?php
138                foreach ($taxonomies as $taxonomy) {
139                    // Ignore the "Format" taxonomy (aside, etc)
140                    if ($taxonomy->name === 'post_format') {
141                        continue;
142                    }
143                    // todo enable for custom taxonomies, and add tests for them
144                    if ($taxonomy->name !== 'category') {
145                        continue;
146                    }
147                    ?>
148                    <h4 style="margin: 0.5rem 0 0.5rem 1.5rem;"><?php echo esc_html($taxonomy->label); ?></h4>
149                    <?php
150                    self::renderTaxonomyTerms($postType, $taxonomy);
151                }
152                ?>
153            </div>
154            <?php
155        }
156    }
157
158    /**
159     * Get the taxonomy terms, as a hierarchical list of nested checkboxes.
160     *
161     * @since 3.0.0
162     * @since 6.0.0 Make static.
163     *
164     * @return void
165     **/
166    public static function renderTaxonomyTerms($postType, $taxonomy, $parent = 0)
167    {
168        $terms = get_terms([
169            'taxonomy'   => $taxonomy->name,
170            'hide_empty' => false,
171            'parent'     => $parent,
172        ]);
173
174        if ($terms) {
175            ?>
176            <ul style="margin: 0; padding: 0; list-style:none;">
177                <?php
178                foreach ($terms as $term) :
179                    $inputName = sprintf(
180                        "%s[%s][%s][]",
181                        self::OPTION_NAME,
182                        $postType->name,
183                        $taxonomy->name
184                    );
185                    ?>
186                    <li class="beyondwords-setting__preselect--term" style="margin: 0.5rem 0 0 1.5rem;">
187                        <label>
188                            <input
189                                type="checkbox"
190                                name="<?php echo esc_attr($inputName); ?>"
191                                value="<?php echo esc_attr($term->term_id); ?>"
192                                <?php checked(self::termIsSelected($postType, $taxonomy, $term)) ?>
193                            />
194                            <?php echo esc_html($term->name); ?>
195                        </label>
196                        <?php self::renderTaxonomyTerms($postType, $taxonomy, $term->term_id); ?>
197                    </li>
198                    <?php
199                endforeach;
200                ?>
201                </ul>
202            <?php
203        }
204    }
205
206    /**
207     * Check whether a post type should be preselected.
208     *
209     * @since 6.0.0 Make static.
210     */
211    public static function postTypeIsSelected($postType)
212    {
213        $preselect = get_option(self::OPTION_NAME);
214
215        if (! is_array($preselect)) {
216            return false;
217        }
218
219        return array_key_exists($postType->name, $preselect) && $preselect[$postType->name] === '1';
220    }
221
222    /**
223     * Check whether a taxonomy should be preselected for a post type.
224     *
225     * @since 6.0.0 Make static.
226     */
227    public static function taxonomyIsSelected($postType, $taxonomy)
228    {
229        $preselect = get_option(self::OPTION_NAME);
230
231        if (! is_array($preselect)) {
232            return false;
233        }
234
235        if (! isset($preselect[$postType->name]) || ! is_array($preselect[$postType->name])) {
236            return false;
237        }
238
239        return in_array($taxonomy->name, $preselect[$postType->name]);
240    }
241
242    /**
243     * Check whether a term is selected for a post type and taxonomy.
244     *
245     * @since 6.0.0 Make static.
246     */
247    public static function termIsSelected($postType, $taxonomy, $term)
248    {
249        $preselect = get_option(self::OPTION_NAME);
250
251        if (! is_array($preselect)) {
252            return false;
253        }
254
255        if (! isset($preselect[$postType->name]) || ! is_array($preselect[$postType->name])) {
256            return false;
257        }
258
259        if (! isset($preselect[$postType->name][$taxonomy->name]) || ! is_array($preselect[$postType->name][$taxonomy->name])) { // phpcs:ignore Generic.Files.LineLength.TooLong
260            return false;
261        }
262
263        return in_array($term->term_id, $preselect[$postType->name][$taxonomy->name]);
264    }
265
266    /**
267     * Register the component scripts.
268     *
269     * @since 5.0.0
270     * @since 6.0.0 Make static.
271     *
272     * @param string $hook Page hook
273     *
274     * @return void
275     */
276    public static function enqueueScripts($hook)
277    {
278        if ($hook === 'post.php' || $hook === 'post-new.php') {
279            wp_register_script(
280                'beyondwords-settings--preselect-post',
281                BEYONDWORDS__PLUGIN_URI . 'src/Component/Settings/Fields/PreselectGenerateAudio/post.js',
282                ['jquery', 'underscore'],
283                BEYONDWORDS__PLUGIN_VERSION,
284                true
285            );
286
287            // Localize the script with new data
288            $data = [
289                'postType'  => get_post_type(),
290                'preselect' => get_option(self::OPTION_NAME),
291            ];
292
293            wp_localize_script('beyondwords-settings--preselect-post', 'beyondwords', $data);
294
295            wp_enqueue_script('beyondwords-settings--preselect-post');
296        }
297    }
298}