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