PluginProbe
Sharing Image / 3.7
Sharing Image v3.7
3.10 trunk 2.0 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.16 2.0.17 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 3.0 3.1 3.2 3.3 All 29 releases
← All changes | classes/class-settings.php +139 -1117 2.0.23.7 View file →
@@ -12,9 +12,9 @@
12 12 die;
13 13 }
14 14
15 15 /**
16 - * Settings page class
16 + * Settings class.
17 17 *
18 18 * @class Settings
19 19 */
20 20 class Settings {
@@ -25,29 +25,8 @@
25 25 */
26 26 const SCREEN_ID = 'settings_page_sharing-image';
27 27
28 28 /**
29 - * Sharing Image templates options name.
30 - *
31 - * @var string
32 - */
33 - const OPTION_TEMPLATES = 'sharing_image_templates';
34 -
35 - /**
36 - * Sharing Image config options name.
37 - *
38 - * @var string
39 - */
40 - const OPTION_CONFIG = 'sharing_image_config';
41 -
42 - /**
43 - * Sharing Image license options name.
44 - *
45 - * @var string
46 - */
47 - const OPTION_LICENSE = 'sharing_image_license';
48 -
49 - /**
50 29 * Plugin admin menu slug.
51 30 *
52 31 * @var string
53 32 */
@@ -53,64 +32,35 @@
53 32 */
54 33 const SETTINGS_SLUG = 'sharing-image';
55 34
56 35 /**
57 - * Remote licenses API url.
58 - *
59 - * @var string
36 + * Common nonce for settings tabs.
60 37 */
61 - const REMOTE_LICENSES = 'https://wpget.org/sharing-image/verify/';
38 + const SETTINGS_NONCE = 'sharing-image-nonce';
62 39
63 40 /**
64 - * Premium verification event name.
65 - *
66 - * @var string
67 - */
68 - const EVENT_PREMIUM = 'sharing_image_event_premium';
69 -
70 - /**
71 41 * List of settings tabs.
72 42 *
73 43 * @var array
74 44 */
75 - private $tabs = array();
45 + private static $tabs = array();
76 46
77 47 /**
78 - * Settings constructor.
79 - */
80 - public function __construct() {
81 - $this->init_tabs();
82 - }
83 -
84 - /**
85 48 * Init class actions and filters.
86 49 */
87 - public function init() {
88 - add_action( 'admin_menu', array( $this, 'add_menu' ) );
50 + public static function init() {
51 + add_action( 'admin_init', array( __CLASS__, 'init_tabs' ) );
52 + add_action( 'admin_menu', array( __CLASS__, 'add_menu' ) );
53 + add_action( 'admin_title', array( __CLASS__, 'update_settings_title' ) );
54 + add_action( 'admin_init', array( __CLASS__, 'allow_custom_fonts' ) );
89 55
90 - // Handle settings POST requests.
91 - add_action( 'admin_init', array( $this, 'handle_post_requests' ) );
92 -
93 - // Handle settings AJAX requests.
94 - add_action( 'admin_init', array( $this, 'handle_ajax_requests' ) );
95 -
96 - // Allow uploading custom fonts for templates editor.
97 - add_action( 'admin_init', array( $this, 'allow_custom_fonts' ) );
98 -
99 - // Add settings link to plugins list.
100 - add_filter( 'plugin_action_links', array( $this, 'add_settings_link' ), 10, 2 );
101 -
102 - // Update admin title for different tabs.
103 - add_action( 'admin_title', array( $this, 'update_settings_title' ) );
104 -
105 - // Schedule Premium license verification.
106 - add_action( self::EVENT_PREMIUM, array( $this, 'launch_verification_event' ), 10, 1 );
56 + add_filter( 'plugin_action_links', array( __CLASS__, 'add_settings_link' ), 10, 2 );
107 57 }
108 58
109 59 /**
110 60 * Add plugin settings page in WordPress menu.
111 61 */
112 - public function add_menu() {
62 + public static function add_menu() {
113 63 /**
114 64 * Easy way to hide settings page.
115 65 *
116 66 * @param bool $hide_settings Set true to hide settings page.
@@ -125,77 +75,38 @@
125 75 esc_html__( 'Sharing Image settings', 'sharing-image' ),
126 76 esc_html__( 'Sharing Image', 'sharing-image' ),
127 77 'manage_options',
128 78 self::SETTINGS_SLUG,
129 - array( $this, 'display_settings' )
79 + array( __CLASS__, 'display_settings' )
130 80 );
131 81
132 82 // Add required assets and objects.
133 - add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_styles' ) );
134 - add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
83 + add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_styles' ) );
84 + add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) );
135 85 }
136 86
137 87 /**
138 - * Handle settings POST requests.
139 - */
140 - public function handle_post_requests() {
141 - $actions = array(
142 - 'config' => 'save_settings_config',
143 - 'editor' => 'save_settings_template',
144 - 'delete' => 'delete_settings_template',
145 - );
146 -
147 - foreach ( $actions as $key => $method ) {
148 - $action = 'sharing_image_' . $key;
149 -
150 - if ( method_exists( $this, $method ) ) {
151 - add_action( 'admin_post_' . $action, array( $this, $method ) );
152 - }
153 - }
154 - }
155 -
156 - /**
157 - * Handle settings AJAX requests.
158 - */
159 - public function handle_ajax_requests() {
160 - $actions = array(
161 - 'show' => 'show_template_preview',
162 - 'save' => 'save_template_preview',
163 - 'verify' => 'verify_premium_key',
164 - 'revoke' => 'revoke_premium_access',
165 - );
166 -
167 - foreach ( $actions as $key => $method ) {
168 - $action = 'sharing_image_' . $key;
169 -
170 - if ( method_exists( $this, $method ) ) {
171 - add_action( 'wp_ajax_' . $action, array( $this, $method ) );
172 - }
173 - }
174 - }
175 -
176 - /**
177 88 * Allow uploading custom fonts for templates editor.
178 89 * This function may affect the security of the site.
179 90 * Disable font uploading if you are not going to use it.
180 91 */
181 - public function allow_custom_fonts() {
92 + public static function allow_custom_fonts() {
182 93 /**
183 94 * Easy way to disable custom font uploading.
184 95 *
185 - * @param bool $disable_ttf Set true to disable fonts uploading.
96 + * @param bool $disable_fonts Set true to disable fonts uploading.
186 97 */
187 - $disable_fonts = apply_filters( 'sharing_image_allow_custom_fonts', false );
98 + $disable_fonts = apply_filters( 'sharing_image_disable_custom_fonts', false );
188 99
189 100 if ( $disable_fonts ) {
190 101 return;
191 102 }
192 103
193 - // Allow True Type fonts uploading.
194 - add_filter( 'wp_check_filetype_and_ext', array( $this, 'fix_ttf_mime_type' ), 10, 3 );
104 + // Allow fonts uploading.
105 + add_filter( 'wp_check_filetype_and_ext', array( __CLASS__, 'fix_fonts_mime_type' ), 10, 3 );
195 106
196 - // Add new .ttf font mime type.
197 - add_filter( 'upload_mimes', array( $this, 'add_ttf_mime_type' ) );
107 + // Add new .ttf and .otf font mime types.
108 + add_filter( 'upload_mimes', array( __CLASS__, 'add_fonts_mime_type' ) );
198 109 }
199 110
200 111 /**
201 112 * Add settings link to plugins list.
@@ -204,9 +115,9 @@
204 115 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
205 116
206 117 * @return array Array of settings actions.
207 118 */
208 - public function add_settings_link( $actions, $plugin_file ) {
119 + public static function add_settings_link( $actions, $plugin_file ) {
209 120 $actions = (array) $actions;
210 121
211 122 if ( plugin_basename( SHARING_IMAGE_FILE ) === $plugin_file ) {
212 123 $actions[] = sprintf(
@@ -219,249 +130,12 @@
219 130 return $actions;
220 131 }
221 132
222 133 /**
223 - * Save settings config fields.
224 - */
225 - public function save_settings_config() {
226 - check_admin_referer( basename( __FILE__ ), 'sharing_image_nonce' );
227 -
228 - if ( ! current_user_can( 'manage_options' ) ) {
229 - wp_die( esc_html__( 'Sorry, you are not allowed to manage options for this site.', 'sharing-image' ) );
230 - }
231 -
232 - $return = $this->get_tab_link( 'config' );
233 -
234 - if ( null === $return ) {
235 - $return = admin_url( 'options-general.php?page=' . self::SETTINGS_SLUG );
236 - }
237 -
238 - if ( ! isset( $_POST['sharing_image_config'] ) ) {
239 - $this->redirect_with_message( $return, 5 );
240 - }
241 -
242 - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
243 - $config = $this->sanitize_config( wp_unslash( $_POST['sharing_image_config'] ) );
244 -
245 - $this->update_config( $config );
246 -
247 - // Redirect with success message.
248 - $this->redirect_with_message( $return, 1 );
249 - }
250 -
251 - /**
252 - * Save template editor fields.
253 - */
254 - public function save_settings_template() {
255 - check_admin_referer( basename( __FILE__ ), 'sharing_image_nonce' );
256 -
257 - if ( ! current_user_can( 'manage_options' ) ) {
258 - wp_die( esc_html__( 'Sorry, you are not allowed to manage options for this site.', 'sharing-image' ) );
259 - }
260 -
261 - $return = admin_url( 'options-general.php?page=' . self::SETTINGS_SLUG );
262 -
263 - if ( ! isset( $_POST['sharing_image_index'] ) ) {
264 - $this->redirect_with_message( $return, 2 );
265 - }
266 -
267 - $index = absint( wp_unslash( $_POST['sharing_image_index'] ) );
268 -
269 - if ( ! isset( $_POST['sharing_image_editor'] ) ) {
270 - $this->redirect_with_message( $return, 2 );
271 - }
272 -
273 - // Skip 2nd+ templates if the Premium is not active.
274 - if ( $index > 0 && ! $this->is_premium_features() ) {
275 - $this->redirect_with_message( $return, 2 );
276 - }
277 -
278 - $return = add_query_arg( array( 'template' => $index + 1 ), $return );
279 -
280 - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
281 - $editor = $this->sanitize_editor( wp_unslash( $_POST['sharing_image_editor'] ) );
282 -
283 - $this->update_templates( $index, $editor );
284 -
285 - // Redirect with success message.
286 - $this->redirect_with_message( $return, 1 );
287 - }
288 -
289 - /**
290 - * Action to delete template from editor page.
291 - */
292 - public function delete_settings_template() {
293 - check_admin_referer( basename( __FILE__ ), 'nonce' );
294 -
295 - if ( ! current_user_can( 'manage_options' ) ) {
296 - return;
297 - }
298 -
299 - $return = admin_url( 'options-general.php?page=' . self::SETTINGS_SLUG );
300 -
301 - if ( ! isset( $_REQUEST['template'] ) ) {
302 - $this->redirect_with_message( $return, 4 );
303 - }
304 -
305 - // Get index from template ID.
306 - $index = absint( $_REQUEST['template'] ) - 1;
307 -
308 - if ( ! $this->update_templates( $index ) ) {
309 - $this->redirect_with_message( $return, 4 );
310 - }
311 -
312 - $this->redirect_with_message( $return, 3 );
313 - }
314 -
315 - /**
316 - * Show generated template from AJAX request.
317 - */
318 - public function show_template_preview() {
319 - $check = check_ajax_referer( basename( __FILE__ ), 'sharing_image_nonce', false );
320 -
321 - if ( false === $check ) {
322 - wp_send_json_error( __( 'Invalid security token. Reload the page and retry.', 'sharing-image' ), 403 );
323 - }
324 -
325 - if ( ! isset( $_POST['sharing_image_index'] ) ) {
326 - wp_send_json_error( __( 'Poster index undefined.', 'sharing-image' ), 400 );
327 - }
328 -
329 - $index = absint( wp_unslash( $_POST['sharing_image_index'] ) );
330 -
331 - if ( ! isset( $_POST['sharing_image_editor'] ) ) {
332 - wp_send_json_error( __( 'Editor settings are not set.', 'sharing-image' ), 400 );
333 - }
334 -
335 - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
336 - $editor = $this->sanitize_editor( wp_unslash( $_POST['sharing_image_editor'] ) );
337 -
338 - // Show poster using generator class.
339 - $poster = ( new Generator() )->show( $editor, $index );
340 -
341 - if ( is_wp_error( $poster ) ) {
342 - wp_send_json_error( $poster->get_error_message(), 400 );
343 - }
344 - }
345 -
346 - /**
347 - * Show generated template from AJAX request.
348 - */
349 - public function save_template_preview() {
350 - $check = check_ajax_referer( basename( __FILE__ ), 'sharing_image_nonce', false );
351 -
352 - if ( false === $check ) {
353 - wp_send_json_error( __( 'Invalid security token. Reload the page and retry.', 'sharing-image' ), 403 );
354 - }
355 -
356 - if ( ! isset( $_POST['sharing_image_index'] ) ) {
357 - wp_send_json_error( __( 'Poster index undefined.', 'sharing-image' ), 400 );
358 - }
359 -
360 - $index = absint( wp_unslash( $_POST['sharing_image_index'] ) );
361 -
362 - if ( ! isset( $_POST['sharing_image_editor'] ) ) {
363 - wp_send_json_error( __( 'Editor settings are not set.', 'sharing-image' ), 400 );
364 - }
365 -
366 - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
367 - $editor = $this->sanitize_editor( wp_unslash( $_POST['sharing_image_editor'] ) );
368 -
369 - // Save poster using generator class.
370 - $poster = ( new Generator() )->save( $editor, $index );
371 -
372 - if ( is_wp_error( $poster ) ) {
373 - wp_send_json_error( $poster->get_error_message(), 400 );
374 - }
375 -
376 - wp_send_json_success( $poster );
377 - }
378 -
379 - /**
380 - * Verify Premium key from AJAX request.
381 - */
382 - public function verify_premium_key() {
383 - $check = check_ajax_referer( basename( __FILE__ ), 'sharing_image_nonce', false );
384 -
385 - if ( false === $check ) {
386 - wp_send_json_error( __( 'Invalid security token. Reload the page and retry.', 'sharing-image' ), 403 );
387 - }
388 -
389 - if ( empty( $_POST['sharing_image_key'] ) ) {
390 - wp_send_json_error( __( 'Premium key undefined.', 'sharing-image' ), 400 );
391 - }
392 -
393 - $key = sanitize_text_field( wp_unslash( $_POST['sharing_image_key'] ) );
394 -
395 - $args = array(
396 - 'body' => array(
397 - 'key' => $key,
398 - 'domain' => wp_parse_url( site_url(), PHP_URL_HOST ),
399 - ),
400 - );
401 -
402 - $response = wp_remote_post( self::REMOTE_LICENSES, $args );
403 -
404 - if ( is_wp_error( $response ) ) {
405 - wp_send_json_error( __( 'Unable to get a response from the verification server.', 'sharing-image' ), 400 );
406 - }
407 -
408 - $answer = json_decode( $response['body'], true );
409 -
410 - if ( ! isset( $answer['success'] ) ) {
411 - wp_send_json_error( __( 'Unable to get a response from the verification server.', 'sharing-image' ), 400 );
412 - }
413 -
414 - // Remove license verification event.
415 - wp_unschedule_hook( self::EVENT_PREMIUM );
416 -
417 - if ( true === $answer['success'] ) {
418 - $license = $this->update_license( true, $key );
419 -
420 - // Schedule license verification twice daily.
421 - $this->schedule_verification( array( $key ) );
422 -
423 - wp_send_json_success( $license );
424 - }
425 -
426 - $error = array(
427 - 'success' => false,
428 - 'data' => __( 'Verification failed.', 'sharing-image' ),
429 - );
430 -
431 - if ( isset( $answer['result'] ) ) {
432 - $error['code'] = $answer['result'];
433 - }
434 -
435 - $this->update_license( false, $key );
436 -
437 - wp_send_json( $error, 403 );
438 - }
439 -
440 - /**
441 - * Revoke Premium access from AJAX request.
442 - */
443 - public function revoke_premium_access() {
444 - $check = check_ajax_referer( basename( __FILE__ ), 'sharing_image_nonce', false );
445 -
446 - if ( false === $check ) {
447 - wp_send_json_error( __( 'Invalid security token. Reload the page and retry.', 'sharing-image' ), 403 );
448 - }
449 -
450 - // Remove license verification event.
451 - wp_unschedule_hook( self::EVENT_PREMIUM );
452 -
453 - // Disable Premium license.
454 - $license = $this->update_license( false );
455 -
456 - wp_send_json_success( $license );
457 - }
458 -
459 - /**
460 134 * Show plugin settings.
461 135 */
462 - public function display_settings() {
463 - if ( ! $this->is_settings_screen() ) {
136 + public static function display_settings() {
137 + if ( ! self::is_settings_screen() ) {
464 138 return;
465 139 }
466 140
467 141 include_once SHARING_IMAGE_DIR . 'templates/settings.php';
@@ -472,9 +146,9 @@
472 146 do_action( 'sharing_image_settings' );
473 147 }
474 148
475 149 /**
476 - * Fix .ttf files mime.
150 + * Fix .ttf and .otf files mime.
477 151 *
478 152 * @param array $types Values for the extension, mime type, and corrected filename.
479 153 * @param string $file Full path to the file.
480 154 * @param string $filename The name of the file (may differ from $file due to.
@@ -480,9 +154,9 @@
480 154 * @param string $filename The name of the file (may differ from $file due to.
481 155 *
482 156 * @return array List of file types.
483 157 */
484 - public function fix_ttf_mime_type( $types, $file, $filename ) {
158 + public static function fix_fonts_mime_type( $types, $file, $filename ) {
485 159 $extension = pathinfo( $filename, PATHINFO_EXTENSION );
486 160
487 161 if ( 'ttf' === $extension ) {
488 162 $types['ext'] = false;
@@ -488,24 +162,34 @@
488 162 $types['ext'] = false;
489 163
490 164 if ( current_user_can( 'manage_options' ) ) {
491 165 $types['ext'] = 'ttf';
492 - $types['type'] = 'application/x-font-ttf';
166 + $types['type'] = 'font/ttf';
493 167 }
494 168 }
495 169
170 + if ( 'otf' === $extension ) {
171 + $types['ext'] = false;
172 +
173 + if ( current_user_can( 'manage_options' ) ) {
174 + $types['ext'] = 'otf';
175 + $types['type'] = 'font/otf';
176 + }
177 + }
178 +
496 179 return $types;
497 180 }
498 181
499 182 /**
500 - * Add new .ttf font mime type.
183 + * Add new .ttf and .otf font mime types.
501 184 *
502 185 * @param array $types Allowed file types to upload.
503 186 *
504 187 * @return array Allowed file types to upload.
505 188 */
506 - public function add_ttf_mime_type( $types ) {
507 - $types['ttf'] = 'application/x-font-ttf';
189 + public static function add_fonts_mime_type( $types ) {
190 + $types['ttf'] = 'font/ttf';
191 + $types['otf'] = 'font/otf';
508 192
509 193 return $types;
510 194 }
511 195
@@ -511,16 +195,20 @@
511 195
512 196 /**
513 197 * Enqueue settings styles.
514 198 */
515 - public function enqueue_styles() {
516 - if ( ! $this->is_settings_screen() ) {
199 + public static function enqueue_styles() {
200 + if ( ! self::is_settings_screen() ) {
517 201 return;
518 202 }
519 203
204 + $asset = require SHARING_IMAGE_DIR . 'assets/settings/index.asset.php';
205 +
206 + wp_enqueue_media();
207 +
520 208 wp_enqueue_style(
521 209 'sharing-image-settings',
522 - SHARING_IMAGE_URL . 'assets/styles/settings.css',
210 + plugins_url( 'assets/settings/index.css', SHARING_IMAGE_FILE ),
523 211 array(),
524 212 SHARING_IMAGE_VERSION,
525 213 'all'
526 214 );
@@ -528,18 +216,20 @@
528 216
529 217 /**
530 218 * Enqueue settings scripts.
531 219 */
532 - public function enqueue_scripts() {
533 - if ( ! $this->is_settings_screen() ) {
220 + public static function enqueue_scripts() {
221 + if ( ! self::is_settings_screen() ) {
534 222 return;
535 223 }
536 224
225 + $asset = require SHARING_IMAGE_DIR . 'assets/widget/index.asset.php';
226 +
537 227 wp_enqueue_script(
538 228 'sharing-image-settings',
539 - SHARING_IMAGE_URL . 'assets/scripts/settings.js',
540 - array( 'wp-i18n', 'wp-polyfill-url', 'wp-polyfill-formdata' ),
541 - SHARING_IMAGE_VERSION,
229 + plugins_url( 'assets/settings/index.js', SHARING_IMAGE_FILE ),
230 + $asset['dependencies'],
231 + $asset['version'],
542 232 true
543 233 );
544 234
545 235 wp_enqueue_media();
@@ -546,9 +236,9 @@
546 236
547 237 // Translations availible only for WP 5.0+.
548 238 wp_set_script_translations( 'sharing-image-settings', 'sharing-image' );
549 239
550 - $object = $this->create_script_object();
240 + $object = self::create_script_object();
551 241
552 242 // Add settings script object.
553 243 wp_localize_script( 'sharing-image-settings', 'sharingImageSettings', $object );
554 244 }
@@ -553,238 +243,8 @@
553 243 wp_localize_script( 'sharing-image-settings', 'sharingImageSettings', $object );
554 244 }
555 245
556 246 /**
557 - * Get templates list from options.
558 - *
559 - * @return array List of templates.
560 - */
561 - public function get_templates() {
562 - $templates = get_option( self::OPTION_TEMPLATES, array() );
563 -
564 - if ( ! $this->is_premium_features() ) {
565 - $templates = array_slice( $templates, 0, 1 );
566 - }
567 -
568 - /**
569 - * Filters list of templates.
570 - *
571 - * @param array $templates List of templates.
572 - */
573 - return apply_filters( 'sharing_image_get_templates', $templates );
574 - }
575 -
576 - /**
577 - * Update templates using index.
578 - *
579 - * @param int $index Template index to update.
580 - * @param array $editor New template data.
581 - */
582 - public function update_templates( $index, $editor = null ) {
583 - // Method get_templates() is not used to save old templates during Premium switching.
584 - $templates = get_option( self::OPTION_TEMPLATES, array() );
585 -
586 - $templates[ $index ] = $editor;
587 -
588 - if ( null === $editor ) {
589 - unset( $templates[ $index ] );
590 - }
591 -
592 - /**
593 - * Filters list of templates before update in database.
594 - *
595 - * @param array $templates List of reindexed templates.
596 - */
597 - $templates = apply_filters( 'sharing_image_update_templates', array_values( $templates ) );
598 -
599 - return update_option( self::OPTION_TEMPLATES, $templates );
600 - }
601 -
602 - /**
603 - * Get plugin config settings.
604 - *
605 - * @return array List of plugin config settings.
606 - */
607 - public function get_config() {
608 - $config = get_option( self::OPTION_CONFIG, array() );
609 -
610 - /**
611 - * Filters settigns config.
612 - *
613 - * @param array List of plugin config settings.
614 - */
615 - return apply_filters( 'sharing_image_get_config', $config );
616 - }
617 -
618 - /**
619 - * Update config settings.
620 - *
621 - * @param array $config License settings config data.
622 - */
623 - public function update_config( $config ) {
624 - /**
625 - * Filters config options before their update in database.
626 - *
627 - * @param array $config Settings config data.
628 - */
629 - $config = apply_filters( 'sharing_image_update_config', $config );
630 -
631 - update_option( self::OPTION_CONFIG, $config );
632 - }
633 -
634 - /**
635 - * Get plugin license settings.
636 - *
637 - * @return array List of plugin license settings.
638 - */
639 - public function get_license() {
640 - $license = get_option( self::OPTION_LICENSE, array() );
641 -
642 - /**
643 - * Check if the plugin in development mode.
644 - *
645 - * @param bool Current development state. Disabled by default.
646 - */
647 - $develop = apply_filters( 'sharing_image_develop', false );
648 -
649 - if ( $develop ) {
650 - $license['develop'] = true;
651 - }
652 -
653 - /**
654 - * Filters license settings.
655 - *
656 - * @param array List of plugin license settings.
657 - */
658 - return apply_filters( 'sharing_image_get_license', $license );
659 - }
660 -
661 - /**
662 - * Set license options.
663 - *
664 - * @param bool $premium Premium status.
665 - * @param string $key License key.
666 - * @param string $error Verification error code.
667 -
668 - * @return array License options.
669 - */
670 - public function update_license( $premium, $key = '', $error = '' ) {
671 - $license = get_option( self::OPTION_LICENSE, array() );
672 -
673 - $license['premium'] = $premium;
674 -
675 - if ( ! empty( $key ) ) {
676 - $license['key'] = $key;
677 - }
678 -
679 - unset( $license['error'] );
680 -
681 - if ( ! empty( $error ) ) {
682 - $license['error'] = $error;
683 - }
684 -
685 - // Save updated license settings in database.
686 - update_option( self::OPTION_LICENSE, $license );
687 -
688 - return $license;
689 - }
690 -
691 - /**
692 - * Get directory to uploaded posters.
693 - *
694 - * @return array Path and url to upload directory.
695 - */
696 - public function get_upload_dir() {
697 - $config = $this->get_config();
698 -
699 - if ( ! isset( $config['uploads'] ) ) {
700 - $config['uploads'] = 'default';
701 - }
702 -
703 - // Create custom upload directory.
704 - if ( isset( $config['storage'] ) && 'custom' === $config['uploads'] ) {
705 - return $this->create_upload_dir( $config['storage'] );
706 - }
707 -
708 - $uploads = wp_upload_dir();
709 -
710 - /**
711 - * Filters upload directory.
712 - *
713 - * @param array $dir Path and url to upload directory.
714 - */
715 - return apply_filters( 'sharing_image_upload_dir', array( $uploads['path'], $uploads['url'] ) );
716 - }
717 -
718 - /**
719 - * Get generated image file format.
720 - *
721 - * @param string $format Optional. Default image format.
722 -
723 - * @return string Image file format.
724 - */
725 - public function get_file_format( $format = 'jpg' ) {
726 - $config = $this->get_config();
727 -
728 - if ( isset( $config['format'] ) ) {
729 - $format = $config['format'];
730 - }
731 -
732 - /**
733 - * Filters Image file format.
734 - *
735 - * @param string $format Image file format.
736 - */
737 - return apply_filters( 'sharing_image_file_format', $format );
738 - }
739 -
740 - /**
741 - * Get quality of generated poster.
742 - *
743 - * @param int $quality Optional. Default image quality.
744 - *
745 - * @return int Image quality.
746 - */
747 - public function get_quality( $quality = 90 ) {
748 - $config = $this->get_config();
749 -
750 - if ( isset( $config['quality'] ) ) {
751 - $quality = $config['quality'];
752 - }
753 -
754 - /**
755 - * Filters poster image quality.
756 - *
757 - * @param string $quality Image quality.
758 - */
759 - return apply_filters( 'sharing_image_poster_quality', $quality );
760 - }
761 -
762 - /**
763 - * Try to get default poster image data.
764 - * Returns array with image url, width and height.
765 - *
766 - * @see https://developer.wordpress.org/reference/functions/wp_get_attachment_image_src/
767 - *
768 - * @return array|false Array of image data, or boolean false if no image is available.
769 - */
770 - public function get_default_poster_src() {
771 - $config = $this->get_config();
772 -
773 - if ( empty( $config['default'] ) ) {
774 - return false;
775 - }
776 -
777 - $poster = wp_get_attachment_image_src( $config['default'], 'full' );
778 -
779 - if ( is_array( $poster ) ) {
780 - $poster = array_slice( $poster, 0, 3 );
781 - }
782 -
783 - return apply_filters( 'sharing_image_default_poster_src', $poster );
784 - }
785 -
786 - /**
787 247 * Update settings page title.
788 248 *
789 249 * @param string $title Plugin settings page title.
790 250 *
@@ -789,99 +249,34 @@
789 249 * @param string $title Plugin settings page title.
790 250 *
791 251 * @return string Plugin settings title
792 252 */
793 - public function update_settings_title( $title ) {
794 - if ( ! $this->is_settings_screen() ) {
253 + public static function update_settings_title( $title ) {
254 + if ( ! self::is_settings_screen() ) {
795 255 return $title;
796 256 }
797 257
798 - $tab = $this->get_current_tab();
258 + $tab = self::get_current_tab();
799 259
800 - if ( null === $tab ) {
260 + if ( is_null( $tab ) ) {
801 261 return $title;
802 262 }
803 263
804 - if ( empty( $this->tabs[ $tab ]['label'] ) ) {
264 + if ( empty( self::$tabs[ $tab ]['label'] ) ) {
805 265 return $title;
806 266 }
807 267
808 - $label = esc_html( $this->tabs[ $tab ]['label'] );
268 + $label = esc_html( self::$tabs[ $tab ]['label'] );
809 269
810 270 return sprintf( '%s – %s', $label, $title );
811 271 }
812 272
813 273 /**
814 - * Launch scheduled license verification event.
815 - * Do not disable Premium if the verification server does not respond.
816 - *
817 - * @param string $key License key.
818 - */
819 - public function launch_verification_event( $key ) {
820 - $args = array(
821 - 'body' => array(
822 - 'key' => $key,
823 - 'domain' => wp_parse_url( site_url(), PHP_URL_HOST ),
824 - ),
825 - );
826 -
827 - $response = wp_remote_post( self::REMOTE_LICENSES, $args );
828 -
829 - if ( is_wp_error( $response ) ) {
830 - return;
831 - }
832 -
833 - $answer = json_decode( $response['body'], true );
834 -
835 - if ( ! isset( $answer['success'] ) ) {
836 - return;
837 - }
838 -
839 - if ( true === $answer['success'] ) {
840 - return $this->update_license( true, $key );
841 - }
842 -
843 - if ( ! isset( $answer['result'] ) ) {
844 - return $this->update_license( false, $key );
845 - }
846 -
847 - $this->update_license( false, $key, $answer['result'] );
848 - }
849 -
850 - /**
851 - * Check if Premium features availible.
852 - *
853 - * @return bool Whether premium featured enabled.
854 - */
855 - public function is_premium_features() {
856 - $license = $this->get_license();
857 -
858 - if ( ! empty( $license['premium'] ) || ! empty( $license['develop'] ) ) {
859 - return true;
860 - }
861 -
862 - return false;
863 - }
864 -
865 - /**
866 - * Schedule license verification.
867 - *
868 - * @param array $args List of event arguments. License key by default.
869 - */
870 - public function schedule_verification( $args = array() ) {
871 - if ( wp_next_scheduled( self::EVENT_PREMIUM, $args ) ) {
872 - return;
873 - }
874 -
875 - wp_schedule_event( time() + DAY_IN_SECONDS / 2, 'twicedaily', self::EVENT_PREMIUM, $args );
876 - }
877 -
878 - /**
879 274 * Create script object to inject with settings.
880 275 *
881 276 * @return array Filtered script settings object.
882 277 */
883 - private function create_script_object() {
278 + private static function create_script_object() {
884 279 $uploads = wp_get_upload_dir();
885 280
886 281 // Get uploads directory path from WordPress root.
887 282 $basedir = str_replace( ABSPATH, '', $uploads['basedir'] );
@@ -886,19 +281,21 @@
886 281 // Get uploads directory path from WordPress root.
887 282 $basedir = str_replace( ABSPATH, '', $uploads['basedir'] );
888 283
889 284 $object = array(
890 - 'nonce' => wp_create_nonce( basename( __FILE__ ) ),
285 + 'nonce' => wp_create_nonce( self::SETTINGS_NONCE ),
891 286 'links' => array(
892 287 'uploads' => esc_url( admin_url( 'upload.php' ) ),
893 288 'action' => esc_url( admin_url( 'admin-post.php' ) ),
894 - 'premium' => esc_url_raw( $this->get_tab_link( 'premium' ) ),
289 + 'premium' => esc_url_raw( self::get_tab_link( 'premium' ) ),
895 290 'storage' => path_join( $basedir, 'sharing-image' ),
896 291 ),
897 - 'templates' => $this->get_templates(),
898 - 'config' => $this->get_config(),
899 - 'license' => $this->get_license(),
900 - 'fonts' => $this->get_fonts(),
292 + 'fonts' => self::get_fonts(),
293 + 'templates' => Templates::get_templates(),
294 + 'index' => Templates::create_unique_index(),
295 + 'snippets' => Snippets::get_snippets(),
296 + 'config' => Config::get_config(),
297 + 'license' => Premium::get_license(),
901 298 );
902 299
903 300 /**
904 301 * Filters settings script object.
@@ -908,401 +305,14 @@
908 305 return apply_filters( 'sharing_image_settings_object', $object );
909 306 }
910 307
911 308 /**
912 - * Sanitize editor template settings.
913 - *
914 - * @param array $editor Template editor settings.
915 - *
916 - * @return array
917 - */
918 - private function sanitize_editor( $editor ) {
919 - $sanitized = array();
920 -
921 - if ( ! empty( $editor['preview'] ) ) {
922 - $sanitized['preview'] = sanitize_text_field( $editor['preview'] );
923 - }
924 -
925 - if ( ! empty( $editor['title'] ) ) {
926 - $sanitized['title'] = sanitize_text_field( $editor['title'] );
927 - }
928 -
929 - if ( ! empty( $editor['attachment'] ) ) {
930 - $sanitized['attachment'] = absint( $editor['attachment'] );
931 - }
932 -
933 - if ( ! empty( $editor['suspend'] ) ) {
934 - $sanitized['suspend'] = 'suspend';
935 - }
936 -
937 - $sanitized['fill'] = '#000000';
938 -
939 - if ( ! empty( $editor['fill'] ) ) {
940 - $sanitized['fill'] = sanitize_hex_color( $editor['fill'] );
941 - }
942 -
943 - $sanitized['background'] = 'blank';
944 -
945 - if ( isset( $editor['background'] ) ) {
946 - $background = array( 'dynamic', 'blank', 'permanent' );
947 -
948 - // Set default background for permanent option without attachment.
949 - if ( empty( $sanitized['attachment'] ) ) {
950 - $background = array_diff( $background, array( 'permanent' ) );
951 - }
952 -
953 - if ( in_array( $editor['background'], $background, true ) ) {
954 - $sanitized['background'] = $editor['background'];
955 - }
956 - }
957 -
958 - $sanitized['width'] = 1200;
959 -
960 - if ( ! empty( $editor['width'] ) ) {
961 - $sanitized['width'] = absint( $editor['width'] );
962 - }
963 -
964 - $sanitized['height'] = 630;
965 -
966 - if ( ! empty( $editor['height'] ) ) {
967 - $sanitized['height'] = absint( $editor['height'] );
968 - }
969 -
970 - if ( isset( $editor['layers'] ) && is_array( $editor['layers'] ) ) {
971 - $layers = array();
972 -
973 - foreach ( $editor['layers'] as $layer ) {
974 - if ( empty( $layer['type'] ) ) {
975 - continue;
976 - }
977 -
978 - switch ( $layer['type'] ) {
979 - case 'text':
980 - $layers[] = $this->sanitize_text_layer( $layer );
981 - break;
982 -
983 - case 'image':
984 - $layers[] = $this->sanitize_image_layer( $layer );
985 - break;
986 -
987 - case 'filter':
988 - $layers[] = $this->sanitize_filter_layer( $layer );
989 - break;
990 -
991 - case 'rectangle':
992 - $layers[] = $this->sanitize_rectangle_layer( $layer );
993 - break;
994 - }
995 - }
996 -
997 - $sanitized['layers'] = $layers;
998 - }
999 -
1000 - /**
1001 - * Filters template editor sanitized fields.
1002 - *
1003 - * @param array $sanitized List of sanitized editor fields.
1004 - * @param array $editor List of editor fields before sanitization.
1005 - */
1006 - return apply_filters( 'sharing_image_sanitize_editor', $sanitized, $editor );
1007 - }
1008 -
1009 - /**
1010 - * Sanitize template editor text layer.
1011 - *
1012 - * @param array $layer Layer settings.
1013 - *
1014 - * @return array Sanitized layer settings.
1015 - */
1016 - private function sanitize_text_layer( $layer ) {
1017 - $sanitized = array();
1018 -
1019 - // No need to sanitize after switch.
1020 - $sanitized['type'] = $layer['type'];
1021 -
1022 - if ( ! empty( $layer['dynamic'] ) ) {
1023 - $sanitized['dynamic'] = 'dynamic';
1024 - }
1025 -
1026 - if ( isset( $layer['title'] ) ) {
1027 - $sanitized['title'] = sanitize_text_field( $layer['title'] );
1028 - }
1029 -
1030 - if ( isset( $layer['content'] ) ) {
1031 - $sanitized['content'] = sanitize_textarea_field( $layer['content'] );
1032 - }
1033 -
1034 - if ( isset( $layer['sample'] ) ) {
1035 - $sanitized['sample'] = sanitize_textarea_field( $layer['sample'] );
1036 - }
1037 -
1038 - $sanitized['preset'] = 'none';
1039 -
1040 - if ( isset( $layer['preset'] ) ) {
1041 - $preset = array( 'title', 'excerpt' );
1042 -
1043 - if ( in_array( $layer['preset'], $preset, true ) ) {
1044 - $sanitized['preset'] = $layer['preset'];
1045 - }
1046 - }
1047 -
1048 - $sanitized['color'] = '#ffffff';
1049 -
1050 - if ( ! empty( $layer['color'] ) ) {
1051 - $sanitized['color'] = sanitize_hex_color( $layer['color'] );
1052 - }
1053 -
1054 - $sanitized['horizontal'] = 'left';
1055 -
1056 - if ( isset( $layer['horizontal'] ) ) {
1057 - $horizontal = array( 'center', 'right' );
1058 -
1059 - if ( in_array( $layer['horizontal'], $horizontal, true ) ) {
1060 - $sanitized['horizontal'] = $layer['horizontal'];
1061 - }
1062 - }
1063 -
1064 - $sanitized['vertical'] = 'top';
1065 -
1066 - if ( isset( $layer['vertical'] ) ) {
1067 - $vertical = array( 'center', 'bottom' );
1068 -
1069 - if ( in_array( $layer['vertical'], $vertical, true ) ) {
1070 - $sanitized['vertical'] = $layer['vertical'];
1071 - }
1072 - }
1073 -
1074 - if ( isset( $layer['fontsize'] ) ) {
1075 - $sanitized['fontsize'] = absint( $layer['fontsize'] );
1076 - }
1077 -
1078 - if ( isset( $layer['lineheight'] ) ) {
1079 - $sanitized['lineheight'] = (float) $layer['lineheight'];
1080 - }
1081 -
1082 - if ( isset( $layer['fontname'] ) ) {
1083 - $sanitized['fontname'] = sanitize_text_field( $layer['fontname'] );
1084 - }
1085 -
1086 - if ( ! empty( $layer['fontfile'] ) ) {
1087 - $sanitized['fontfile'] = absint( $layer['fontfile'] );
1088 - }
1089 -
1090 - $sizes = array( 'x', 'y', 'width', 'height' );
1091 -
1092 - foreach ( $sizes as $size ) {
1093 - if ( ! isset( $layer[ $size ] ) || '' === $layer[ $size ] ) {
1094 - continue;
1095 - }
1096 -
1097 - $sanitized[ $size ] = absint( $layer[ $size ] );
1098 - }
1099 -
1100 - return $sanitized;
1101 - }
1102 -
1103 - /**
1104 - * Sanitize template editor image layer.
1105 - *
1106 - * @param array $layer Layer settings.
1107 - *
1108 - * @return array Sanitized image layer settings.
1109 - */
1110 - private function sanitize_image_layer( $layer ) {
1111 - $sanitized = array();
1112 -
1113 - // No need to sanitize after switch.
1114 - $sanitized['type'] = $layer['type'];
1115 -
1116 - if ( ! empty( $layer['attachment'] ) ) {
1117 - $sanitized['attachment'] = absint( $layer['attachment'] );
1118 - }
1119 -
1120 - $sizes = array( 'x', 'y', 'width', 'height' );
1121 -
1122 - foreach ( $sizes as $size ) {
1123 - if ( ! isset( $layer[ $size ] ) || '' === $layer[ $size ] ) {
1124 - continue;
1125 - }
1126 -
1127 - $sanitized[ $size ] = absint( $layer[ $size ] );
1128 - }
1129 -
1130 - return $sanitized;
1131 - }
1132 -
1133 - /**
1134 - * Sanitize template editor filter layer.
1135 - *
1136 - * @param array $layer Layer settings.
1137 - *
1138 - * @return array Sanitized filter layer settings.
1139 - */
1140 - private function sanitize_filter_layer( $layer ) {
1141 - $sanitized = array();
1142 -
1143 - // No need to sanitize after switch.
1144 - $sanitized['type'] = $layer['type'];
1145 -
1146 - if ( ! empty( $layer['grayscale'] ) ) {
1147 - $sanitized['grayscale'] = 'grayscale';
1148 - }
1149 -
1150 - if ( ! empty( $layer['blur'] ) ) {
1151 - $sanitized['blur'] = 'blur';
1152 - }
1153 -
1154 - $sanitized['brightness'] = 0;
1155 -
1156 - if ( isset( $layer['brightness'] ) ) {
1157 - $brightness = (int) $layer['brightness'];
1158 -
1159 - if ( $brightness >= -100 && $brightness <= 100 ) {
1160 - $sanitized['brightness'] = $brightness;
1161 - }
1162 - }
1163 -
1164 - $sanitized['contrast'] = 0;
1165 -
1166 - if ( isset( $layer['contrast'] ) ) {
1167 - $contrast = (int) $layer['contrast'];
1168 -
1169 - if ( $contrast >= -100 && $contrast <= 100 ) {
1170 - $sanitized['contrast'] = $contrast;
1171 - }
1172 - }
1173 -
1174 - $sanitized['blackout'] = 0;
1175 -
1176 - if ( isset( $layer['blackout'] ) ) {
1177 - $blackout = (int) $layer['blackout'];
1178 -
1179 - if ( $blackout >= 0 && $blackout <= 100 ) {
1180 - $sanitized['blackout'] = $blackout;
1181 - }
1182 - }
1183 -
1184 - return $sanitized;
1185 - }
1186 -
1187 - /**
1188 - * Sanitize template editor rectagle layer.
1189 - *
1190 - * @param array $layer Layer settings.
1191 - *
1192 - * @return array Sanitized rectangle layer settings.
1193 - */
1194 - private function sanitize_rectangle_layer( $layer ) {
1195 - $sanitized = array();
1196 -
1197 - // No need to sanitize after switch.
1198 - $sanitized['type'] = $layer['type'];
1199 -
1200 - if ( ! empty( $layer['outline'] ) ) {
1201 - $sanitized['outline'] = 'outline';
1202 - }
1203 -
1204 - $sanitized['color'] = '#ffffff';
1205 -
1206 - if ( ! empty( $layer['color'] ) ) {
1207 - $sanitized['color'] = sanitize_hex_color( $layer['color'] );
1208 - }
1209 -
1210 - $sanitized['opacity'] = 0;
1211 -
1212 - if ( isset( $layer['opacity'] ) ) {
1213 - $opacity = (float) $layer['opacity'];
1214 -
1215 - if ( $opacity >= 0 && $opacity <= 100 ) {
1216 - $sanitized['opacity'] = $opacity;
1217 - }
1218 - }
1219 -
1220 - $sanitized['thickness'] = 0;
1221 -
1222 - if ( isset( $layer['thickness'] ) ) {
1223 - $thickness = (int) $layer['thickness'];
1224 -
1225 - if ( $thickness >= 0 && $thickness <= 50 ) {
1226 - $sanitized['thickness'] = $thickness;
1227 - }
1228 - }
1229 -
1230 - $sizes = array( 'x', 'y', 'width', 'height' );
1231 -
1232 - foreach ( $sizes as $size ) {
1233 - if ( ! isset( $layer[ $size ] ) || '' === $layer[ $size ] ) {
1234 - continue;
1235 - }
1236 -
1237 - $sanitized[ $size ] = absint( $layer[ $size ] );
1238 - }
1239 -
1240 - return $sanitized;
1241 - }
1242 -
1243 - /**
1244 - * Sanitize config settings.
1245 - *
1246 - * @param array $config Config settings.
1247 - *
1248 - * @return array Sanitized config settings.
1249 - */
1250 - private function sanitize_config( $config ) {
1251 - $sanitized = array();
1252 -
1253 - if ( ! empty( $config['default'] ) ) {
1254 - $sanitized['default'] = absint( $config['default'] );
1255 - }
1256 -
1257 - $sanitized['format'] = 'jpg';
1258 -
1259 - if ( isset( $config['format'] ) ) {
1260 - $format = $config['format'];
1261 -
1262 - if ( in_array( $format, array( 'jpg', 'png' ), true ) ) {
1263 - $sanitized['format'] = $config['format'];
1264 - }
1265 - }
1266 -
1267 - if ( isset( $config['quality'] ) ) {
1268 - $quality = (int) $config['quality'];
1269 -
1270 - if ( $quality >= 1 && $quality <= 100 ) {
1271 - $sanitized['quality'] = $quality;
1272 - }
1273 - }
1274 -
1275 - $sanitized['uploads'] = 'default';
1276 -
1277 - if ( isset( $config['uploads'] ) ) {
1278 - $uploads = $config['uploads'];
1279 -
1280 - if ( in_array( $uploads, array( 'custom', 'default' ), true ) ) {
1281 - $sanitized['uploads'] = $config['uploads'];
1282 - }
1283 - }
1284 -
1285 - if ( isset( $config['storage'] ) ) {
1286 - $sanitized['storage'] = sanitize_text_field( $config['storage'] );
1287 - }
1288 -
1289 - /**
1290 - * Filters template editor sanitized fields.
1291 - *
1292 - * @param array $sanitized List of sanitized config fields.
1293 - * @param array $config List of config fields before sanitization.
1294 - */
1295 - return apply_filters( 'sharing_image_sanitize_config', $sanitized, $config );
1296 - }
1297 -
1298 - /**
1299 309 * Show settings tab template.
1300 310 */
1301 - private function show_settings_section() {
1302 - $tab = $this->get_current_tab();
311 + private static function show_settings_section() {
312 + $tab = self::get_current_tab();
1303 313
1304 - if ( null === $tab ) {
314 + if ( is_null( $tab ) ) {
1305 315 return;
1306 316 }
1307 317
1308 318 include_once SHARING_IMAGE_DIR . "templates/{$tab}.php";
@@ -1310,32 +320,60 @@
1310 320
1311 321 /**
1312 322 * Show settings messages and errors after post actions.
1313 323 */
1314 - private function show_settings_message() {
324 + private static function show_settings_message() {
1315 325 // phpcs:ignore WordPress.Security.NonceVerification
1316 326 $message = isset( $_GET['message'] ) ? absint( $_GET['message'] ) : 0;
1317 327
1318 328 switch ( $message ) {
1319 329 case 1:
1320 - add_settings_error( 'sharing-image', 'sharing-image', __( 'Settings successfully updated.', 'sharing-image' ), 'updated' );
330 + add_settings_error( 'sharing-image', 'sharing-image', __( 'Settings updated successfully.', 'sharing-image' ), 'updated' );
1321 331 break;
1322 332
1323 333 case 2:
1324 - add_settings_error( 'sharing-image', 'sharing-image', __( 'Failed to save template settings.', 'sharing-image' ) );
334 + add_settings_error( 'sharing-image', 'sharing-image', __( 'Unable to save template settings.', 'sharing-image' ) );
1325 335 break;
1326 336
1327 337 case 3:
1328 - add_settings_error( 'sharing-image', 'sharing-image', __( 'Template successfully deleted.', 'sharing-image' ), 'updated' );
338 + add_settings_error( 'sharing-image', 'sharing-image', __( 'Template deleted successfully.', 'sharing-image' ), 'updated' );
1329 339 break;
1330 340
1331 341 case 4:
1332 - add_settings_error( 'sharing-image', 'sharing-image', __( 'Failed to delete template.', 'sharing-image' ) );
342 + add_settings_error( 'sharing-image', 'sharing-image', __( 'Unable to delete template.', 'sharing-image' ) );
1333 343 break;
1334 344
1335 345 case 5:
1336 - add_settings_error( 'sharing-image', 'sharing-image', __( 'Failed to save configuration settings.', 'sharing-image' ) );
346 + add_settings_error( 'sharing-image', 'sharing-image', __( 'Unable to save configuration settings.', 'sharing-image' ) );
1337 347 break;
348 +
349 + case 6:
350 + add_settings_error( 'sharing-image', 'sharing-image', __( 'Error uploading file. Please try again.', 'sharing-image' ) );
351 + break;
352 +
353 + case 7:
354 + add_settings_error( 'sharing-image', 'sharing-image', __( 'The imported file is empty.', 'sharing-image' ) );
355 + break;
356 +
357 + case 8:
358 + add_settings_error( 'sharing-image', 'sharing-image', __( 'The maximum allowed number of templates has been reached. Please upgrade to Premium.', 'sharing-image' ) );
359 + break;
360 +
361 + case 9:
362 + add_settings_error( 'sharing-image', 'sharing-image', __( 'Templates imported successfully.', 'sharing-image' ), 'updated' );
363 + break;
364 +
365 + case 10:
366 + add_settings_error( 'sharing-image', 'sharing-image', __( 'Unable to clone template.', 'sharing-image' ) );
367 + break;
368 +
369 + case 11:
370 + add_settings_error( 'sharing-image', 'sharing-image', __( 'Template cloned successfully.', 'sharing-image' ), 'updated' );
371 + break;
372 +
373 + case 12:
374 + add_settings_error( 'sharing-image', 'sharing-image', __( 'Posters removed successfully.', 'sharing-image' ), 'updated' );
375 + break;
1338 376 }
1339 377
1340 378 settings_errors( 'sharing-image' );
1341 379 }
@@ -1342,9 +380,9 @@
1342 380
1343 381 /**
1344 382 * Set list of settings page tabs.
1345 383 */
1346 - private function init_tabs() {
384 + public static function init_tabs() {
1347 385 $tabs = array(
1348 386 'templates' => array(
1349 387 'label' => __( 'Templates', 'sharing-image' ),
1350 388 'link' => admin_url( 'options-general.php?page=' . self::SETTINGS_SLUG ),
@@ -1353,8 +391,12 @@
1353 391 'config' => array(
1354 392 'label' => __( 'Configuration', 'sharing-image' ),
1355 393 'link' => admin_url( 'options-general.php?page=' . self::SETTINGS_SLUG . '&tab=config' ),
1356 394 ),
395 + 'tools' => array(
396 + 'label' => __( 'Tools', 'sharing-image' ),
397 + 'link' => admin_url( 'options-general.php?page=' . self::SETTINGS_SLUG . '&tab=tools' ),
398 + ),
1357 399 'premium' => array(
1358 400 'label' => __( 'Premium', 'sharing-image' ),
1359 401 'link' => admin_url( 'options-general.php?page=' . self::SETTINGS_SLUG . '&tab=premium' ),
1360 402 ),
@@ -1364,18 +406,18 @@
1364 406 * Filters tabs in settings page.
1365 407 *
1366 408 * @param array $tabs List of settings tabs.
1367 409 */
1368 - $this->tabs = apply_filters( 'sharing_image_settings_tabs', $tabs );
410 + self::$tabs = apply_filters( 'sharing_image_settings_tabs', $tabs );
1369 411 }
1370 412
1371 413 /**
1372 414 * Print menu on settings page.
1373 415 */
1374 - private function show_settings_menu() {
1375 - $current = $this->get_current_tab();
416 + private static function show_settings_menu() {
417 + $current = self::get_current_tab();
1376 418
1377 - foreach ( $this->tabs as $tab => $args ) {
419 + foreach ( self::$tabs as $tab => $args ) {
1378 420 $classes = array(
1379 421 'sharing-image-tab',
1380 422 );
1381 423
@@ -1382,9 +424,9 @@
1382 424 if ( $current === $tab ) {
1383 425 $classes[] = 'active';
1384 426 }
1385 427
1386 - if ( null === $current && ! empty( $args['default'] ) ) {
428 + if ( is_null( $current ) && ! empty( $args['default'] ) ) {
1387 429 $classes[] = 'active';
1388 430 }
1389 431
1390 432 printf(
@@ -1400,16 +442,19 @@
1400 442 * Get availible fonts.
1401 443 *
1402 444 * @return array List of availible poster fonts.
1403 445 */
1404 - private function get_fonts() {
446 + private static function get_fonts() {
1405 447 $fonts = array(
1406 - 'open-sans' => 'Open Sans',
1407 - 'merriweather' => 'Merriweather',
1408 - 'roboto-slab' => 'Roboto Slab',
1409 - 'ubuntu' => 'Ubuntu',
1410 - 'rubik-bold' => 'Rubik Bold',
1411 - 'montserrat' => 'Montserrat',
448 + 'open-sans' => 'Open Sans',
449 + 'open-sans-light' => 'Open Sans Light',
450 + 'open-sans-bold' => 'Open Sans Bold',
451 + 'merriweather' => 'Merriweather',
452 + 'roboto-slab' => 'Roboto Slab',
453 + 'ubuntu' => 'Ubuntu',
454 + 'rubik-bold' => 'Rubik Bold',
455 + 'alice' => 'Alice',
456 + 'lobster' => 'Lobster',
1412 457 );
1413 458
1414 459 /**
1415 460 * Filters poster fonts.
@@ -1425,14 +470,14 @@
1425 470 * @param string $tab Tab name.
1426 471 *
1427 472 * @return string|null Tab link.
1428 473 */
1429 - private function get_tab_link( $tab ) {
1430 - if ( empty( $this->tabs[ $tab ]['link'] ) ) {
1431 - return null;
474 + public static function get_tab_link( $tab ) {
475 + if ( empty( self::$tabs[ $tab ]['link'] ) ) {
476 + return admin_url( 'options-general.php?page=' . self::SETTINGS_SLUG );
1432 477 }
1433 478
1434 - return $this->tabs[ $tab ]['link'];
479 + return self::$tabs[ $tab ]['link'];
1435 480 }
1436 481
1437 482 /**
1438 483 * Get current tab.
@@ -1438,14 +483,14 @@
1438 483 * Get current tab.
1439 484 *
1440 485 * @return string|null Current tab name.
1441 486 */
1442 - private function get_current_tab() {
487 + public static function get_current_tab() {
1443 488 // phpcs:disable WordPress.Security.NonceVerification
1444 489 if ( ! empty( $_GET['tab'] ) ) {
1445 490 $tab = sanitize_file_name( wp_unslash( $_GET['tab'] ) );
1446 491
1447 - if ( array_key_exists( $tab, $this->tabs ) ) {
492 + if ( array_key_exists( $tab, self::$tabs ) ) {
1448 493 return $tab;
1449 494 }
1450 495 }
1451 496 // phpcs:enable WordPress.Security.NonceVerification
@@ -1453,40 +498,17 @@
1453 498 return null;
1454 499 }
1455 500
1456 501 /**
1457 - * Create upload directory and return its path and url
1458 - *
1459 - * @param string $storage Relative directory path.
1460 - *
1461 - * @return array Path and url to upload directory.
1462 - */
1463 - private function create_upload_dir( $storage ) {
1464 - $storage = trim( $storage, '/' );
1465 -
1466 - /**
1467 - * Change permissions when creating new folders.
1468 - *
1469 - * @param int $permissions New directory access permissions. By default 0755.
1470 - */
1471 - $permissions = apply_filters( 'sharing_image_directory_permissions', 0755 );
1472 -
1473 - // We do not pay attention to the possible error.
1474 - mkdir( ABSPATH . $storage, $permissions, true );
1475 -
1476 - return array( ABSPATH . $storage, site_url( $storage ) );
1477 - }
1478 -
1479 - /**
1480 502 * Add message id to the back link and redirect
1481 503 *
1482 - * @param string $return Redirect link.
1483 - * @param int $message Settings error message id.
504 + * @param string $redirect Redirect link.
505 + * @param int $message Settings error message id.
1484 506 */
1485 - private function redirect_with_message( $return, $message ) {
1486 - $return = add_query_arg( array( 'message' => $message ), $return );
507 + public static function redirect_with_message( $redirect, $message ) {
508 + $redirect = add_query_arg( array( 'message' => $message ), $redirect );
1487 509
1488 - wp_safe_redirect( $return );
510 + wp_safe_redirect( $redirect );
1489 511 exit;
1490 512 }
1491 513
1492 514 /**
@@ -1493,9 +515,9 @@
1493 515 * Is current admin screen the plugin options screen.
1494 516 *
1495 517 * @return bool Whether the settings screen of this plugin is displayed or not.
1496 518 */
1497 - private function is_settings_screen() {
519 + private static function is_settings_screen() {
1498 520 $current_screen = get_current_screen();
1499 521
1500 522 if ( $current_screen && self::SCREEN_ID === $current_screen->id ) {
1501 523 return true;