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 / Settings / Settings.php

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

523 lines 15.9 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 settings.
7 *
8 * @package Beyondwords\Wordpress
9 * @author Stuart McAlpine <stu@beyondwords.io>
10 * @since 3.0.0
11 */
12
13 namespace Beyondwords\Wordpress\Component\Settings;
14
15 use Beyondwords\Wordpress\Component\Settings\Languages\Languages;
16 use Beyondwords\Wordpress\Component\Settings\Preselect\Preselect;
17 use Beyondwords\Wordpress\Component\Settings\SettingsUtils;
18 use Beyondwords\Wordpress\Core\Core;
19 use Beyondwords\Wordpress\Core\Environment;
20
21 /**
22 * Settings setup
23 *
24 * @since 3.0.0
25 */
26 class Settings
27 {
28 private $apiClient;
29
30 /**
31 * Constructor
32 */
33 public function __construct($apiClient)
34 {
35 $this->apiClient = $apiClient;
36
37 add_action('admin_menu', array($this, 'addOptionsPage'));
38 add_action('admin_init', array($this, 'init'));
39 add_action('admin_notices', array($this, 'printPluginAdminNotices'));
40 add_action('rest_api_init', array($this, 'restApiInit'));
41
42 add_filter('plugin_action_links_speechkit/speechkit.php', array($this, 'addSettingsLinkToPluginPage'));
43
44 add_action('updated_option', array($this, 'updatedOption'), 99, 3);
45 add_action('added_option', array($this, 'addedOption'), 99, 2);
46 }
47
48 /**
49 * Add items to the WordPress admin menu.
50 *
51 * @since 3.0.0
52 *
53 * @return void
54 */
55 public function addOptionsPage()
56 {
57 // Settings > BeyondWords
58 add_options_page(
59 __('BeyondWords', 'speechkit'),
60 __('BeyondWords', 'speechkit'),
61 'manage_options',
62 'beyondwords',
63 array($this, 'createAdminInterface')
64 );
65 }
66
67 /**
68 * Init Settings.
69 *
70 * =====
71 * Basic
72 * =====
73 * 'api_key' => '',
74 * 'project_id' => '',
75 *
76 * ==============
77 * Player
78 * ==============
79 * 'version' => '0',
80 *
81 * ==============
82 * Generate audio
83 * ==============
84 * 'preselect' => array('post' => '1', 'page' => '1'),
85 *
86 * ========
87 * Advanced
88 * ========
89 * 'merge_excerpt' => false,
90 *
91 * @since 3.0.0
92 */
93 public function init()
94 {
95 // Add Settings Section: Basic
96 add_settings_section(
97 'basic',
98 __('Basic settings', 'speechkit'),
99 array($this, 'basicSectionCallback'),
100 'beyondwords'
101 );
102
103 if (SettingsUtils::hasApiSettings()) {
104 // Add Settings Section: Player
105 add_settings_section(
106 'player',
107 __('Player settings', 'speechkit'),
108 array($this, 'playerSectionCallback'),
109 'beyondwords'
110 );
111
112 // Add Settings Section: Content
113 add_settings_section(
114 'content',
115 __('Content settings', 'speechkit'),
116 array($this, 'contentSectionCallback'),
117 'beyondwords'
118 );
119
120 // Add Settings Section: Generate audio
121 add_settings_section(
122 'generate-audio',
123 __('‘Generate audio’ settings', 'speechkit'),
124 array($this, 'generateAudioSectionCallback'),
125 'beyondwords'
126 );
127 }
128 }
129
130 /**
131 * "Basic section" callback
132 *
133 * @since 3.0.0
134 *
135 * @return void
136 **/
137 public function basicSectionCallback()
138 {
139 delete_transient('beyondwords_settings_errors');
140 ?>
141 <p class="description">
142 <?php
143 _e(
144 'The details we need to authenticate your BeyondWords account. For more options, head to your BeyondWords dashboard.', // phpcs:ignore Generic.Files.LineLength.TooLong
145 'speechkit'
146 );
147 ?>
148 </p>
149 <?php
150 }
151
152 /**
153 * "Player section" callback
154 *
155 * @since 4.0.0
156 *
157 * @return void
158 **/
159 public function playerSectionCallback()
160 {
161 ?>
162 <p class="description">
163 <?php
164 _e(
165 'Upgrade to the latest player version for the newest features.', // phpcs:ignore Generic.Files.LineLength.TooLong
166 'speechkit'
167 );
168 ?>
169 </p>
170 <?php
171 }
172
173 /**
174 * "Content" section callback
175 *
176 * @since 3.0.0
177 *
178 * @return void
179 **/
180 public function contentSectionCallback()
181 {
182 ?>
183 <p class="description">
184 <?php
185 _e(
186 'By default, BeyondWords will process your titles and body content into audio.', // phpcs:ignore Generic.Files.LineLength.TooLong
187 'speechkit'
188 );
189 ?>
190 </p>
191 <?php
192 }
193
194 /**
195 * ‘Generate audio’ section callback.
196 *
197 * @since 3.0.0
198 *
199 * @return void
200 **/
201 public function generateAudioSectionCallback()
202 {
203 ?>
204 <p class="description">
205 <?php
206 _e(
207 'The ‘Generate audio’ checkbox in the BeyondWords sidebar will be automatically checked for selected post types. The default setting can be manually overridden.', // phpcs:ignore Generic.Files.LineLength.TooLong
208 'speechkit'
209 );
210 ?>
211 </p>
212 <p class="description">
213 <?php
214 _e(
215 'Uncheck a post type to view its Categories. You can then set defaults at a category level. Make sure to check all relevant boxes.', // phpcs:ignore Generic.Files.LineLength.TooLong
216 'speechkit'
217 );
218 ?>
219 </p>
220 <p class="description">
221 <em>
222 <?php
223 _e(
224 'The default WordPress ‘Categories’ taxonomy is currently the only taxonomy supported.',
225 'speechkit'
226 );
227 ?>
228 </em>
229 </p>
230 <?php
231 }
232
233 public function addSettingsLinkToPluginPage($links)
234 {
235 $links[] = '<a href="' .
236 esc_url(admin_url('options-general.php?page=beyondwords')) .
237 '">' . __('Settings', 'speechkit') . '</a>';
238 return $links;
239 }
240
241
242
243 public function createAdminInterface()
244 {
245 ?>
246 <div class="wrap">
247
248 <form
249 id="beyondwords-plugin-settings"
250 action="<?php echo esc_url(admin_url('options.php')); ?>"
251 method="post"
252 >
253
254 <h1><?php _e('BeyondWords settings', 'speechkit'); ?></h1>
255
256 <?php
257 $projectId = get_option('beyondwords_project_id');
258 $playerReverted = get_transient('beyondwords_player_reverted');
259
260 if ($projectId) :
261 ?>
262 <p>
263 <a
264 class="button button-secondary"
265 href="<?php echo esc_url(Environment::getDashboardUrl()); ?>"
266 target="_blank"
267 >
268 <?php _e('BeyondWords dashboard', 'speechkit'); ?>
269 </a>
270 </p>
271 <?php
272 endif;
273
274 if ($playerReverted) :
275 ?>
276 <div id="beyondwords-player-reverted-notice" class="notice notice-error">
277 <p>
278 <span class="dashicons dashicons-editor-help"></span>
279 <?php
280 printf(
281 /* translators: %s is replaced with a "let us know" link */
282 esc_html__('It looks like you tried the "Latest" player and switched back to the "Legacy" player. If you experienced any issues switching player please %s so we can help.', 'speechkit'), // phpcs:ignore Generic.Files.LineLength.TooLong
283 sprintf(
284 '<a href="mailto:support@beyondwords.io?subject=%s">%s</a>',
285 esc_attr__('WordPress support: Latest player', 'speechkit'),
286 esc_html__('let us know', 'speechkit')
287 )
288 );
289 ?>
290 </p>
291 </div>
292 <?php
293 endif;
294 if (SettingsUtils::hasApiSettings()) :
295 ?>
296 <div id="beyondwords-player-location-notice" class="notice notice-info">
297 <p>
298 <span class="dashicons dashicons-info"></span>
299 <?php _e(
300 'The player will appear before the first part of <code>the_content()</code> by default. You can change the location via the WordPress Editor.', // phpcs:ignore Generic.Files.LineLength.TooLong
301 'speechkit'
302 );
303 ?>
304 </p>
305 </div>
306 <?php
307 endif;
308
309 settings_fields('beyondwords');
310 do_settings_sections('beyondwords');
311
312 if (SettingsUtils::hasApiSettings()) {
313 submit_button('Save Settings');
314 } else {
315 submit_button('Continue setup');
316 }
317 ?>
318 </form>
319 </div>
320 <?php
321 }
322
323 /**
324 * Print Admin Notices.
325 *
326 * @since 3.0.0
327 *
328 * @return void
329 */
330 public function printPluginAdminNotices()
331 {
332 $hasApiSettings = SettingsUtils::hasApiSettings();
333 $settingsErrors = get_transient('beyondwords_settings_errors');
334
335 if (is_array($settingsErrors) && count($settingsErrors)) :
336 ?>
337 <div class="notice notice-error">
338 <p>
339 <strong>
340 <?php
341 printf(
342 /* translators: %s is replaced with a "plugin settings" link */
343 esc_html__('To use BeyondWords, please update the %s.', 'speechkit'),
344 sprintf(
345 '<a href="%s">%s</a>',
346 esc_url(admin_url('options-general.php?page=beyondwords')),
347 esc_html__('plugin settings', 'speechkit')
348 )
349 );
350 ?>
351 </strong>
352 </p>
353 <ul class="ul-disc">
354 <?php
355 foreach ($settingsErrors as $error) {
356 printf(
357 '<li>%s</li>',
358 // Only allow links with href and target attributes
359 wp_kses(
360 $error,
361 array(
362 'a' => array(
363 'href' => array(),
364 'target' => array(),
365 ),
366 'b' => array(),
367 'strong' => array(),
368 'i' => array(),
369 'em' => array(),
370 )
371 )
372 );
373 }
374 ?>
375 </ul>
376 </div>
377
378 <?php
379 elseif (false === $hasApiSettings) :
380 ?>
381 <div class="notice notice-info">
382 <p>
383 <strong>
384 <?php
385 printf(
386 esc_html__('To use BeyondWords, please update the %s.', 'speechkit'),
387 sprintf(
388 '<a href="%s">%s</a>',
389 esc_url(admin_url('options-general.php?page=beyondwords')),
390 esc_html__('plugin settings', 'speechkit')
391 )
392 );
393 ?>
394 </strong>
395 </p>
396 <p>
397 <?php _e('Don’t have a BeyondWords account yet?', 'speechkit'); ?>
398 </p>
399 <p>
400 <a
401 class="button button-secondary"
402 href="<?php echo esc_url(sprintf('%s/auth/signup', Environment::getDashboardUrl())); ?>"
403 target="_blank"
404 >
405 <?php _e('Sign up free', 'speechkit'); ?>
406 </a>
407 </p>
408 </div>
409 <?php
410 endif;
411 }
412
413 /**
414 * Register WP REST API route
415 *
416 * @return void
417 */
418 public function restApiInit()
419 {
420 // settings endpoint
421 register_rest_route('beyondwords/v1', '/settings', array(
422 'methods' => \WP_REST_Server::READABLE,
423 'callback' => array($this, 'restApiResponse'),
424 'permission_callback' => function () {
425 return current_user_can('edit_posts');
426 },
427 ));
428 }
429
430 /**
431 * WP REST API response (required for the Gutenberg editor).
432 *
433 * DO NOT expose ALL settings e.g. be sure to never expose the API key.
434 *
435 * @return \WP_REST_Response
436 */
437 public function restApiResponse()
438 {
439 return new \WP_REST_Response([
440 'apiKey' => get_option('beyondwords_api_key', ''),
441 'projectId' => get_option('beyondwords_project_id', ''),
442 'preselect' => get_option('beyondwords_preselect', Preselect::DEFAULT_PRESELECT),
443 'languages' => get_option('beyondwords_languages', Languages::DEFAULT_LANGUAGES),
444 'debug' => defined('BEYONDWORDS_DEBUG') ? boolval(BEYONDWORDS_DEBUG) : false,
445 ]);
446 }
447
448 /**
449 * Check API creds are valid whenever any setting is added.
450 *
451 * @SuppressWarnings(PHPMD.UnusedFormalParameter)
452 *
453 * @since 4.0.0
454 *
455 * @return void
456 */
457 public function addedOption($optionName, $value)
458 {
459 if ($optionName === 'beyondwords_settings_updated') {
460 $this->checkApiCreds();
461 }
462 }
463
464 /**
465 * Check API creds are valid whenever the settings are updated.
466 *
467 * @SuppressWarnings(PHPMD.UnusedFormalParameter)
468 *
469 * @since 4.0.0
470 *
471 * @return void
472 */
473 public function updatedOption($optionName, $oldValue, $value)
474 {
475 if ($optionName === 'beyondwords_settings_updated') {
476 $this->checkApiCreds();
477 }
478 }
479
480 /**
481 * Check to see if user has valid BeyondWords API credentials by performing
482 * a GET request using the API Key and Project ID.
483 *
484 * @since 4.0.0
485 *
486 * @return void
487 */
488 public function checkApiCreds()
489 {
490 // Assume invalid connection
491 delete_option('beyondwords_valid_api_connection');
492
493 $apiKey = get_option('beyondwords_api_key');
494 $projectId = get_option('beyondwords_project_id');
495
496 if (empty($apiKey) || empty($projectId)) {
497 return;
498 }
499
500 $project = $this->apiClient->getProject();
501
502 $validConnection = (
503 is_array($project)
504 && array_key_exists('id', $project)
505 && strval($project['id']) === $projectId
506 );
507
508 if ($validConnection) {
509 // Store date of last check
510 update_option('beyondwords_valid_api_connection', gmdate(DATE_ISO8601));
511 } else {
512 $errors = get_transient('beyondwords_settings_errors', []);
513
514 $errors['Settings/ValidApiConnection'] = __(
515 'Please check and re-enter your BeyondWords API key and project ID. They appear to be invalid.',
516 'speechkit'
517 );
518
519 set_transient('beyondwords_settings_errors', $errors);
520 }
521 }
522 }
523