PluginProbe
BeyondWords – AI audio for publishers / 4.2.4
BeyondWords – AI audio for publishers v4.2.4
7.1.0 trunk 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.1.0 4.1.1 4.1.2 4.2.0 4.2.1 4.2.2 4.2.3 4.2.4 4.3.0 4.4.0 4.5.0 4.5.1 4.6.0 4.6.1 4.6.2 4.7.0 All 43 releases
speechkit / src / Component / Post / SelectVoice / SelectVoice.php

SelectVoice.php in BeyondWords – AI audio for publishers 4.2.4, at src/Component/Post/SelectVoice/SelectVoice.php

329 lines 9.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 /**
6 * BeyondWords Component: Select Voice
7 *
8 * @package Beyondwords\Wordpress
9 * @author Stuart McAlpine <stu@beyondwords.io>
10 * @since 4.0.0
11 */
12
13 namespace Beyondwords\Wordpress\Component\Post\SelectVoice;
14
15 use Beyondwords\Wordpress\Core\ApiClient;
16 use Beyondwords\Wordpress\Core\Core;
17 use Beyondwords\Wordpress\Core\CoreUtils;
18 use Beyondwords\Wordpress\Component\Post\PostMetaUtils;
19 use Beyondwords\Wordpress\Component\Settings\Languages\Languages;
20 use Beyondwords\Wordpress\Component\Settings\SettingsUtils;
21
22 /**
23 * SelectVoice setup
24 *
25 * @since 4.0.0
26 */
27 class SelectVoice
28 {
29 /**
30 * API Client
31 */
32 private $apiClient;
33
34 /**
35 * Constructor
36 */
37 public function __construct($apiClient)
38 {
39 $this->apiClient = $apiClient;
40
41 add_action('rest_api_init', array($this, 'restApiInit'));
42 add_action('admin_enqueue_scripts', array($this, 'adminEnqueueScripts'));
43
44 add_action('wp_loaded', function () {
45 $postTypes = SettingsUtils::getSupportedPostTypes();
46
47 if (is_array($postTypes)) {
48 foreach ($postTypes as $postType) {
49 add_action("save_post_{$postType}", array($this, 'save'), 10);
50 }
51 }
52 });
53 }
54
55 /**
56 * @since 4.0.0
57 */
58 public function element($post)
59 {
60 if (! get_option('beyondwords_languages')) {
61 return;
62 }
63
64 $currentLanguageId = get_post_meta($post->ID, 'beyondwords_language_id', true);
65 $currentVoiceId = get_post_meta($post->ID, 'beyondwords_body_voice_id', true);
66
67 $languages = $this->getFilteredLanguages();
68 $voices = [];
69
70 if ($currentLanguageId) {
71 $voices = $this->apiClient->getVoices($currentLanguageId);
72 }
73
74 wp_nonce_field('beyondwords_select_voice', 'beyondwords_select_voice_nonce');
75 ?>
76 <p
77 id="beyondwords-metabox-select-voice--language-id"
78 class="post-attributes-label-wrapper page-template-label-wrapper"
79 >
80 <label class="post-attributes-label" for="beyondwords_language_id">
81 Language
82 </label>
83 </p>
84 <select id="beyondwords_language_id" name="beyondwords_language_id" style="width: 100%;">
85 <option value="">Project default</option>
86 <?php
87 foreach ($languages as $language) {
88 printf(
89 '<option value="%s" %s>%s</option>',
90 esc_attr($language['id']),
91 selected(strval($language['id']), $currentLanguageId),
92 esc_html($language['name'])
93 );
94 }
95 ?>
96 </select>
97 <p
98 id="beyondwords-metabox-select-voice--voice-id"
99 class="post-attributes-label-wrapper page-template-label-wrapper"
100 >
101 <label class="post-attributes-label" for="beyondwords_voice_id">
102 Voice
103 </label>
104 </p>
105 <select
106 id="beyondwords_voice_id"
107 name="beyondwords_voice_id"
108 style="width: 100%;"
109 <?php echo disabled(!strval($currentLanguageId)) ?>
110 >
111 <option value=""></option>
112 <?php
113 foreach ($voices as $voice) {
114 printf(
115 '<option value="%s" %s>%s</option>',
116 esc_attr($voice['id']),
117 selected(strval($voice['id']), $currentVoiceId),
118 esc_html($voice['name'])
119 );
120 }
121 ?>
122 </select>
123 <?php
124 }
125
126 /**
127 * Save the meta when the post is saved.
128 *
129 * @since 4.0.0
130 *
131 * @param int $postId The ID of the post being saved.
132 */
133 public function save($postId)
134 {
135 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
136 return $postId;
137 }
138
139 // "save_post" can be triggered at other times, so verify this request came from the our component
140 if (
141 ! isset($_POST['beyondwords_language_id']) ||
142 ! isset($_POST['beyondwords_voice_id']) ||
143 ! isset($_POST['beyondwords_select_voice_nonce'])
144 ) {
145 return $postId;
146 }
147
148 // "save_post" can be triggered at other times, so verify this request came from the our component
149 if (
150 ! wp_verify_nonce(
151 sanitize_text_field($_POST['beyondwords_select_voice_nonce']),
152 'beyondwords_select_voice'
153 )
154 ) {
155 return $postId;
156 }
157
158 $languageId = sanitize_text_field($_POST['beyondwords_language_id']);
159
160 if (! empty($languageId)) {
161 update_post_meta($postId, 'beyondwords_language_id', $languageId);
162 } else {
163 delete_post_meta($postId, 'beyondwords_language_id');
164 }
165
166 $voiceId = sanitize_text_field($_POST['beyondwords_voice_id']);
167
168 if (! empty($voiceId)) {
169 update_post_meta($postId, 'beyondwords_body_voice_id', $voiceId);
170 update_post_meta($postId, 'beyondwords_title_voice_id', $voiceId);
171 update_post_meta($postId, 'beyondwords_summary_voice_id', $voiceId);
172 } else {
173 delete_post_meta($postId, 'beyondwords_body_voice_id');
174 delete_post_meta($postId, 'beyondwords_title_voice_id');
175 delete_post_meta($postId, 'beyondwords_summary_voice_id');
176 }
177
178 return $postId;
179 }
180
181 /**
182 * Register WP REST API route
183 *
184 * @since 4.0.0
185 *
186 * @return void
187 */
188 public function restApiInit()
189 {
190 // Languages endpoint
191 register_rest_route('beyondwords/v1', '/languages', array(
192 'methods' => \WP_REST_Server::READABLE,
193 'callback' => array($this, 'languagesRestApiResponse'),
194 'permission_callback' => function () {
195 return current_user_can('edit_posts');
196 },
197 ));
198
199 // Voices endpoint
200 register_rest_route('beyondwords/v1', '/languages/(?P<languageId>[0-9]+)/voices', array(
201 'methods' => \WP_REST_Server::READABLE,
202 'callback' => array($this, 'voicesRestApiResponse'),
203 'permission_callback' => function () {
204 return current_user_can('edit_posts');
205 },
206 ));
207 }
208
209 /**
210 * Get languages from BeyondWords API and filter by "Languages" plugin setting.
211 *
212 * @since 4.0.0
213 *
214 * @return array Array of languages
215 */
216 public function getFilteredLanguages()
217 {
218 $languages = $this->apiClient->getLanguages();
219 $languagesSetting = get_option('beyondwords_languages', Languages::DEFAULT_LANGUAGES);
220
221 // Filter languages according to "Languages" plugin setting
222 if (is_array($languages) && is_array($languagesSetting)) {
223 $languages = array_values(array_filter($languages, function ($language) {
224 return $this->languageIsInSettings($language);
225 }));
226 }
227
228 return $languages;
229 }
230
231 /**
232 * Get languages from BeyondWords API and filter by "Languages" plugin setting.
233 *
234 * @since 4.0.0
235 *
236 * @return array Array of languages
237 */
238 public function languageIsInSettings($language)
239 {
240 if (! is_array($language)) {
241 return false;
242 }
243
244 if (! array_key_exists('id', $language)) {
245 return false;
246 }
247
248 $languagesSetting = get_option('beyondwords_languages', Languages::DEFAULT_LANGUAGES);
249
250 if (! is_array($languagesSetting)) {
251 return false;
252 }
253
254 if (! in_array(strval($language['id']), $languagesSetting)) {
255 return false;
256 }
257
258 return true;
259 }
260
261 /**
262 * "Languages" WP REST API response (required for the Gutenberg editor).
263 *
264 * @since 4.0.0
265 *
266 * @return \WP_REST_Response
267 */
268 public function languagesRestApiResponse()
269 {
270 $languages = $this->getFilteredLanguages();
271
272 return new \WP_REST_Response($languages);
273 }
274
275 /**
276 * "Voices" WP REST API response (required for the Gutenberg editor
277 * and Block Editor).
278 *
279 * @since 4.0.0
280 *
281 * @return \WP_REST_Response
282 */
283 public function voicesRestApiResponse(\WP_REST_Request $data)
284 {
285 $params = $data->get_url_params();
286
287 $voices = $this->apiClient->getVoices($params['languageId']);
288
289 return new \WP_REST_Response($voices);
290 }
291
292
293 /**
294 * Register the component scripts.
295 *
296 * @since 4.0.0
297 *
298 * @param string $hook Page hook
299 *
300 * @return void
301 */
302 public function adminEnqueueScripts($hook)
303 {
304 if (! CoreUtils::isGutenbergPage() && ( $hook === 'post.php' || $hook === 'post-new.php')) {
305 wp_register_script(
306 'beyondwords-metabox--select-voice',
307 BEYONDWORDS__PLUGIN_URI . 'src/Component/Post/SelectVoice/classic-metabox.js',
308 ['jquery', 'underscore'],
309 BEYONDWORDS__PLUGIN_VERSION,
310 true
311 );
312
313 /**
314 * Localize the script to handle ajax requests
315 */
316 wp_localize_script(
317 'beyondwords-metabox--select-voice',
318 'beyondwordsData',
319 array(
320 'nonce' => wp_create_nonce('wp_rest'),
321 'root' => esc_url_raw(rest_url()),
322 )
323 );
324
325 wp_enqueue_script('beyondwords-metabox--select-voice');
326 }
327 }
328 }
329