Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
94.52% covered (success)
94.52%
69 / 73
60.00% covered (danger)
60.00%
3 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
GenerateAudio
94.44% covered (success)
94.44%
68 / 72
60.00% covered (danger)
60.00%
3 / 5
20.07
0.00% covered (danger)
0.00%
0 / 1
 init
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
3
 admin_enqueue_scripts
92.31% covered (success)
92.31%
24 / 26
0.00% covered (danger)
0.00%
0 / 1
7.02
 should_preselect_generate_audio
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 element
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
2
 save
87.50% covered (success)
87.50%
14 / 16
0.00% covered (danger)
0.00%
0 / 1
7.10
1<?php
2
3declare( strict_types = 1 );
4
5/**
6 * BeyondWords Component: Generate audio
7 *
8 * @package BeyondWords\Editor\Components
9 * @author  Stuart McAlpine <stu@beyondwords.io>
10 * @since   3.0.0
11 * @since   7.0.0 Refactored to BeyondWords namespace with snake_case methods.
12 */
13
14namespace BeyondWords\Editor\Components;
15
16/**
17 * GenerateAudio
18 *
19 * @since 3.0.0
20 * @since 7.0.0 Refactored to BeyondWords namespace with snake_case methods.
21 */
22defined( 'ABSPATH' ) || exit;
23
24class GenerateAudio {
25
26    /**
27     * Init.
28     *
29     * @since 4.0.0
30     * @since 6.0.0 Make static.
31     * @since 7.0.0 Refactored to BeyondWords namespace with snake_case methods.
32     */
33    public static function init() {
34        add_action(
35            'wp_loaded',
36            function (): void {
37                $post_types = \BeyondWords\Settings\Utils::get_compatible_post_types();
38
39                if ( is_array( $post_types ) ) {
40                    foreach ( $post_types as $post_type ) {
41                        add_action( "save_post_{$post_type}", [ self::class, 'save'], 10 );
42                    }
43                }
44            }
45        );
46
47        add_action( 'admin_enqueue_scripts', [ self::class, 'admin_enqueue_scripts' ] );
48    }
49
50    /**
51     * Enqueue the classic-editor Generate audio script.
52     *
53     * Always enqueued (the caption sync needs it); `terms` mode additionally
54     * localizes the term data used to live-update the checkbox.
55     *
56     * @since 7.0.0
57     * @since 7.0.0 Always enqueued (for the caption); preselect data is optional.
58     *
59     * @param string $hook Current admin page hook.
60     */
61    public static function admin_enqueue_scripts( $hook ): void {
62        if ( \BeyondWords\Core\Utils::is_gutenberg_page() ) {
63            return;
64        }
65
66        if ( 'post.php' !== $hook && 'post-new.php' !== $hook ) {
67            return;
68        }
69
70        $post_type = get_post_type();
71
72        if ( ! in_array( $post_type, \BeyondWords\Settings\Utils::get_compatible_post_types(), true ) ) {
73            return;
74        }
75
76        wp_register_script(
77            'beyondwords-metabox--generate-audio',
78            BEYONDWORDS__PLUGIN_URI . 'src/editor/components/generate-audio/classic-metabox.js',
79            [],
80            BEYONDWORDS__PLUGIN_VERSION,
81            true
82        );
83
84        if ( \BeyondWords\Settings\Preselect::MODE_TERMS === \BeyondWords\Settings\Preselect::get_mode( $post_type ) ) {
85            $terms = \BeyondWords\Settings\Preselect::get_selected_terms( $post_type );
86
87            if ( ! empty( $terms ) ) {
88                wp_localize_script(
89                    'beyondwords-metabox--generate-audio',
90                    'beyondwordsPreselect',
91                    [
92                        'mode'  => \BeyondWords\Settings\Preselect::MODE_TERMS,
93                        'terms' => $terms,
94                    ]
95                );
96            }
97        }
98
99        wp_enqueue_script( 'beyondwords-metabox--generate-audio' );
100    }
101
102    /**
103     * Check whether the "Generate audio" checkbox should be preselected.
104     *
105     * @since 6.0.0 Make static.
106     * @since 7.0.0 Refactored to BeyondWords namespace with snake_case methods.
107     * @since 7.0.0 Delegated to Preselect; term-gating reinstated.
108     *
109     * @param \WP_Post|int $post The post object or ID.
110     */
111    public static function should_preselect_generate_audio( $post ) {
112        return \BeyondWords\Settings\Preselect::should_preselect_for_post( $post );
113    }
114
115    /**
116     * Render the element.
117     *
118     * @since 6.0.0 Make static and refactor generate audio check.
119     * @since 7.0.0 Refactored to BeyondWords namespace with snake_case methods.
120     */
121    public static function element( $post ) {
122        wp_nonce_field( 'beyondwords_generate_audio', 'beyondwords_generate_audio_nonce' );
123
124        $generate_audio = \BeyondWords\Post\Meta::has_generate_audio( $post->ID );
125
126        // State-reflecting caption; the data attributes let classic-metabox.js keep
127        // it in step as the checkbox toggles (mirrors the block editor toggle).
128        $label_enabled  = __( 'Generation enabled', 'speechkit' );
129        $label_disabled = __( 'Generation disabled', 'speechkit' );
130        ?>
131        <!--  checkbox -->
132        <p id="beyondwords-metabox-generate-audio">
133            <input
134                type="checkbox"
135                id="beyondwords_generate_audio"
136                name="beyondwords_generate_audio"
137                value="1"
138                <?php checked( $generate_audio ); ?>
139            />
140            <label for="beyondwords_generate_audio">
141                <span
142                    id="beyondwords-generate-audio-label"
143                    data-label-enabled="<?php echo esc_attr( $label_enabled ); ?>"
144                    data-label-disabled="<?php echo esc_attr( $label_disabled ); ?>"
145                ><?php echo esc_html( $generate_audio ? $label_enabled : $label_disabled ); ?></span>
146            </label>
147        </p>
148        <?php
149    }
150
151    /**
152     * Save the meta when the post is saved.
153     *
154     * @since 6.0.0 Make static.
155     * @since 7.0.0 Refactored to BeyondWords namespace with snake_case methods.
156     *
157     * @param int $post_id The ID of the post being saved.
158     */
159    public static function save( $post_id ) {
160        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
161            return $post_id;
162        }
163
164        if (
165            ! isset( $_POST['beyondwords_generate_audio_nonce'] ) ||
166            ! wp_verify_nonce(
167                sanitize_key( $_POST['beyondwords_generate_audio_nonce'] ),
168                'beyondwords_generate_audio'
169            )
170        ) {
171            return $post_id;
172        }
173
174        if ( ! current_user_can( 'edit_post', $post_id ) ) {
175            return $post_id;
176        }
177
178        if ( isset( $_POST['beyondwords_generate_audio'] ) ) {
179            update_post_meta( $post_id, 'beyondwords_generate_audio', '1' );
180        } else {
181            delete_post_meta( $post_id, 'speechkit_error_message' );
182            delete_post_meta( $post_id, 'beyondwords_error_message' );
183            update_post_meta( $post_id, 'beyondwords_generate_audio', '0' );
184        }
185
186        return $post_id;
187    }
188}