PluginProbe
BeyondWords – AI audio for publishers / 4.5.0
BeyondWords – AI audio for publishers v4.5.0
7.2.0 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 All 44 releases
speechkit / src / Component / Post / SelectVoice / SelectVoice.php

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

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