PluginProbe
Sharing Image / 2.0.9
Sharing Image v2.0.9
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
sharing-image / classes / class-widget.php

class-widget.php in Sharing Image 2.0.9, at classes/class-widget.php

564 lines 13.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Widget class
4 *
5 * @package sharing-image
6 * @author Anton Lukin
7 */
8
9 namespace Sharing_Image;
10
11 if ( ! defined( 'ABSPATH' ) ) {
12 die;
13 }
14
15 /**
16 * Widget class
17 *
18 * @class Widget
19 */
20 class Widget {
21 /**
22 * Post meta key to store poster image.
23 *
24 * @var string
25 */
26 const WIDGET_META = '_sharing_image';
27
28 /**
29 * The instance of Settings class.
30 *
31 * @var instance
32 */
33 private $settings;
34
35 /**
36 * Widget constructor.
37 */
38 public function __construct() {
39 $this->settings = new Settings();
40 }
41
42 /**
43 * Init class actions and filters.
44 */
45 public function init() {
46 // Init taxonomy term widget.
47 add_action( 'admin_init', array( $this, 'init_taxonomy_widget' ) );
48
49 // Init post metabox widget.
50 add_action( 'admin_init', array( $this, 'init_metabox_widget' ) );
51
52 // Handle metabox AJAX requests.
53 add_action( 'admin_init', array( $this, 'handle_ajax_requests' ) );
54
55 // Try to autogenerate poster if it is needed.
56 add_action( 'wp_insert_post', array( $this, 'autogenerate_poster' ) );
57 }
58
59 /**
60 * Init metabox on post editing page.
61 */
62 public function init_metabox_widget() {
63 /**
64 * Easy way to hide metabox.
65 *
66 * @param bool $hide_metabox Set true to hide metabox.
67 */
68 $hide_metabox = apply_filters( 'sharing_image_hide_metabox', false );
69
70 if ( $hide_metabox ) {
71 return;
72 }
73
74 add_action( 'add_meta_boxes', array( $this, 'add_metabox' ) );
75
76 // Handle actions on post save.
77 add_action( 'save_post', array( $this, 'save_metabox' ), 10, 2 );
78
79 // Add required assets and objects.
80 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_metabox_assets' ) );
81 }
82
83 /**
84 * Init widget on taxonomy term editing page.
85 */
86 public function init_taxonomy_widget() {
87 // Skip if the Premium is not active.
88 if ( ! $this->settings->is_premium_features() ) {
89 return;
90 }
91
92 $taxonomies = $this->get_widget_taxonomies();
93
94 foreach ( $taxonomies as $taxonomy ) {
95 // Display taxonomy term widget.
96 add_action( $taxonomy . '_edit_form', array( $this, 'display_widget' ), 10, 2 );
97
98 // Save taxonomy term meta.
99 add_action( 'edited_' . $taxonomy, array( $this, 'save_taxonomy' ) );
100
101 // Enqueue term assets.
102 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_taxonomy_assets' ) );
103 }
104 }
105
106 /**
107 * Add metabox to post editing page.
108 */
109 public function add_metabox() {
110 add_meta_box(
111 'sharing-image-metabox',
112 esc_html__( 'Sharing Image', 'sharing image' ),
113 array( $this, 'display_widget' ),
114 $this->get_metabox_post_types(),
115 'side'
116 );
117 }
118
119 /**
120 * Add metabox scripts and styles to admin page.
121 *
122 * @param string $hook_suffix The current admin page.
123 */
124 public function enqueue_metabox_assets( $hook_suffix ) {
125 if ( ! in_array( $hook_suffix, array( 'post.php', 'post-new.php' ), true ) ) {
126 return;
127 }
128
129 $screen = get_current_screen();
130
131 if ( ! in_array( $screen->post_type, $this->get_metabox_post_types(), true ) ) {
132 return;
133 }
134
135 $post = get_post();
136
137 // Get post meta for current post ID.
138 $meta = get_post_meta( $post->ID, self::WIDGET_META, true );
139
140 $this->enqueue_scripts( $this->create_script_object( $meta, 'metabox' ) );
141 $this->enqueue_styles();
142 }
143
144 /**
145 * Add widget scripts and styles to admin page.
146 *
147 * @param string $hook_suffix The current admin page.
148 */
149 public function enqueue_taxonomy_assets( $hook_suffix ) {
150 if ( 'term.php' !== $hook_suffix ) {
151 return;
152 }
153
154 $screen = get_current_screen();
155
156 if ( ! in_array( $screen->taxonomy, $this->get_widget_taxonomies(), true ) ) {
157 return;
158 }
159
160 // phpcs:disable WordPress.Security.NonceVerification
161 if ( ! isset( $_REQUEST['tag_ID'] ) ) {
162 return;
163 }
164
165 $term_id = absint( $_REQUEST['tag_ID'] );
166 // phpcs:enable WordPress.Security.NonceVerification
167
168 // Get term meta for current term ID.
169 $meta = get_term_meta( $term_id, self::WIDGET_META, true );
170
171 $this->enqueue_scripts( $this->create_script_object( $meta, 'taxonomy' ) );
172 $this->enqueue_styles();
173 }
174
175 /**
176 * Save metabox data.
177 *
178 * @param int $post_id Post ID.
179 * @param WP_Post $post Post object.
180 */
181 public function save_metabox( $post_id, $post ) {
182 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
183 return;
184 }
185
186 if ( wp_is_post_revision( $post_id ) ) {
187 return;
188 }
189
190 if ( ! current_user_can( 'edit_post', $post_id ) ) {
191 return;
192 }
193
194 if ( ! isset( $_POST['sharing_image_nonce'] ) ) {
195 return;
196 }
197
198 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
199 if ( ! wp_verify_nonce( $_POST['sharing_image_nonce'], basename( __FILE__ ) ) ) {
200 return;
201 }
202
203 if ( ! isset( $_POST['sharing_image_picker'] ) ) {
204 return;
205 }
206
207 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
208 $meta = $this->sanitize_picker( wp_unslash( $_POST['sharing_image_picker'] ) );
209
210 /**
211 * Filters updated post meta.
212 *
213 * @param string $meta Updated post meta.
214 * @param string $post_id Post ID.
215 */
216 $meta = apply_filters( 'sharing_image_update_post_meta', $meta, $post_id );
217
218 // Update post meta.
219 update_post_meta( $post_id, self::WIDGET_META, $meta );
220 }
221
222 /**
223 * Save taxonomy fields.
224 *
225 * @param int $term_id Term ID.
226 */
227 public function save_taxonomy( $term_id ) {
228 if ( ! isset( $_POST['sharing_image_nonce'] ) ) {
229 return;
230 }
231
232 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
233 if ( ! wp_verify_nonce( $_POST['sharing_image_nonce'], basename( __FILE__ ) ) ) {
234 return;
235 }
236
237 if ( ! current_user_can( 'edit_term', $term_id ) ) {
238 return;
239 }
240
241 if ( ! isset( $_POST['sharing_image_picker'] ) ) {
242 return;
243 }
244
245 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
246 $meta = $this->sanitize_picker( wp_unslash( $_POST['sharing_image_picker'] ) );
247
248 /**
249 * Filters term meta on update.
250 *
251 * @param string $meta Updated term meta.
252 * @param string $term_id Term ID.
253 */
254 $meta = apply_filters( 'sharing_image_update_term_meta', $meta, $term_id );
255
256 update_term_meta( $term_id, self::WIDGET_META, $meta );
257 }
258
259 /**
260 * Display widget.
261 */
262 public function display_widget() {
263 include_once SHARING_IMAGE_DIR . 'templates/widget.php';
264
265 /**
266 * Fires on widget template including.
267 */
268 do_action( 'sharing_image_widget' );
269 }
270
271 /**
272 * Handle widget AJAX requests.
273 */
274 public function handle_ajax_requests() {
275 $actions = array(
276 'generate' => 'generate_poster',
277 'rebuild' => 'rebuild_metabox',
278 );
279
280 foreach ( $actions as $key => $method ) {
281 $action = 'sharing_image_' . $key;
282
283 if ( method_exists( $this, $method ) ) {
284 add_action( 'wp_ajax_' . $action, array( $this, $method ) );
285 }
286 }
287 }
288
289 /**
290 * Generate poster by AJAX request.
291 */
292 public function generate_poster() {
293 $check = check_ajax_referer( basename( __FILE__ ), 'sharing_image_nonce', false );
294
295 if ( false === $check ) {
296 wp_send_json_error( __( 'Invalid security token. Reload the page and retry.', 'sharing-image' ), 403 );
297 }
298
299 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
300 $picker = $this->sanitize_picker( wp_unslash( $_POST['sharing_image_picker'] ) );
301
302 // Compose new poster.
303 $poster = ( new Generator() )->compose( $picker );
304
305 if ( is_wp_error( $poster ) ) {
306 wp_send_json_error( $poster->get_error_message(), 400 );
307 }
308
309 wp_send_json_success( $poster );
310 }
311
312 /**
313 * Send metabox config object to rebuild it on frontend.
314 */
315 public function rebuild_metabox() {
316 $check = check_ajax_referer( basename( __FILE__ ), 'sharing_image_nonce', false );
317
318 if ( false === $check ) {
319 wp_send_json_error( __( 'Invalid security token. Reload the page and retry.', 'sharing-image' ), 403 );
320 }
321
322 if ( empty( $_POST['post'] ) ) {
323 return;
324 }
325
326 $post_id = absint( $_POST['post'] );
327
328 // Get post meta for current post ID.
329 $meta = get_post_meta( $post_id, self::WIDGET_META, true );
330
331 wp_send_json_success( $this->create_script_object( $meta, 'metabox' ) );
332 }
333
334 /**
335 * Generate poster by AJAX request.
336 *
337 * @param integer $post_id Desired post_id.
338 *
339 * @return string|false Generated poster link.
340 */
341 public function autogenerate_poster( $post_id ) {
342 $meta = get_post_meta( $post_id, self::WIDGET_META, true );
343
344 if ( empty( $meta ) ) {
345 return;
346 }
347
348 if ( ! empty( $meta['poster'] ) ) {
349 return;
350 }
351
352 $config = $this->settings->get_config();
353
354 if ( ! isset( $config['autogenerate'] ) ) {
355 return;
356 }
357
358 if ( 'manual' === $config['autogenerate'] ) {
359 return;
360 }
361
362 $meta['template'] = absint( $config['autogenerate'] );
363
364 // Generate new poster using post data.
365 $poster = ( new Generator() )->autogenerate( $meta['template'], $post_id );
366
367 /**
368 * Filters autogenerated poster data.
369 *
370 * @param array|false $poster Poster image, width and height data or false if undefined.
371 * @param string $post_id Post ID.
372 */
373 $poster = apply_filters( 'sharing_image_autogenerated_poster', $poster, $post_id );
374
375 if ( empty( $poster ) ) {
376 return;
377 }
378
379 $meta = wp_parse_args( $poster, $meta );
380
381 // Update post meta with new poster link.
382 update_post_meta( $post_id, self::WIDGET_META, $meta );
383 }
384
385 /**
386 * Enqueue widget styles.
387 */
388 private function enqueue_styles() {
389 wp_enqueue_style(
390 'sharing-image-widget',
391 SHARING_IMAGE_URL . 'assets/styles/widget.css',
392 array(),
393 SHARING_IMAGE_VERSION,
394 'all'
395 );
396 }
397
398 /**
399 * Enqueue widget scripts.
400 *
401 * @param array $object Widget data object.
402 */
403 private function enqueue_scripts( $object ) {
404 wp_enqueue_media();
405
406 wp_enqueue_script(
407 'sharing-image-widget',
408 SHARING_IMAGE_URL . 'assets/scripts/widget.js',
409 array( 'wp-i18n', 'wp-polyfill-formdata' ),
410 SHARING_IMAGE_VERSION,
411 true
412 );
413
414 wp_set_script_translations( 'sharing-image-settings', 'sharing-image' );
415
416 // Add widget script object.
417 wp_localize_script( 'sharing-image-widget', 'sharingImageWidget', $object );
418 }
419
420 /**
421 * Sanitize picker widget data before saving.
422 *
423 * @param array $picker Widget POST data.
424
425 * @return array Sanitized picker fields.
426 */
427 private function sanitize_picker( $picker ) {
428 $sanitized = array();
429
430 if ( isset( $picker['poster'] ) ) {
431 $sanitized['poster'] = sanitize_text_field( $picker['poster'] );
432 }
433
434 if ( ! empty( $picker['width'] ) ) {
435 $sanitized['width'] = absint( $picker['width'] );
436 }
437
438 if ( ! empty( $picker['height'] ) ) {
439 $sanitized['height'] = absint( $picker['height'] );
440 }
441
442 $template = 0;
443
444 if ( isset( $picker['template'] ) ) {
445 $template = absint( $picker['template'] );
446
447 if ( count( $this->settings->get_templates() ) <= $template ) {
448 $template = 0;
449 }
450 }
451
452 $sanitized['template'] = $template;
453
454 if ( isset( $picker['fieldset'] ) ) {
455 $fieldset = $picker['fieldset'];
456
457 foreach ( $fieldset as $key => $fields ) {
458 $sanitized['fieldset'][ $key ] = $this->sanitize_fieldset( $fields );
459 }
460 }
461
462 /**
463 * Filters widget picker sanitized fields.
464 *
465 * @param array $sanitized List of sanitized picker fields.
466 * @param array $picker List of picker fields before sanitization.
467 */
468 return apply_filters( 'sharing_image_sanitize_picker', $sanitized, $picker );
469 }
470
471 /**
472 * Sanitize picker widget fieldset list.
473 *
474 * @param array $fields Fieldset widget list.
475 *
476 * @return array Sanitized fieldset data.
477 */
478 public function sanitize_fieldset( $fields ) {
479 $sanitized = array();
480
481 if ( ! empty( $fields['captions'] ) && is_array( $fields['captions'] ) ) {
482 $sanitized['captions'] = array_map( 'sanitize_textarea_field', $fields['captions'] );
483 }
484
485 if ( ! empty( $fields['attachment'] ) ) {
486 $sanitized['attachment'] = absint( $fields['attachment'] );
487 }
488
489 return $sanitized;
490 }
491
492 /**
493 * Create script object to inject with widget.
494 *
495 * @param array $meta Term or Post meta data.
496 * @param string $context Widget context. For example: metabox or taxonomy.
497
498 * @return array Filtered widget script object.
499 */
500 private function create_script_object( $meta, $context ) {
501 $object = array(
502 'meta' => $meta,
503 'nonce' => wp_create_nonce( basename( __FILE__ ) ),
504 'context' => $context,
505
506 'links' => array(
507 'uploads' => esc_url( admin_url( 'upload.php' ) ),
508 ),
509
510 'templates' => $this->settings->get_templates(),
511 );
512
513 /**
514 * Filter widget script object.
515 *
516 * @param array $object Array of widget script object.
517 */
518 return apply_filters( 'sharing_image_widget_object', $object );
519 }
520
521 /**
522 * Get an array of post types where the metabox is displayed.
523 *
524 * @return array Array of post types.
525 */
526 private function get_metabox_post_types() {
527 $post_types = get_post_types(
528 array(
529 'public' => true,
530 )
531 );
532
533 unset( $post_types['attachment'] );
534
535 /**
536 * Filter widget post types.
537 *
538 * @param array $post_types Array of post types for which the metabox is displayed.
539 */
540 return apply_filters( 'sharing_image_metabox_post_types', array_values( $post_types ) );
541 }
542
543 /**
544 * Get an array of taxonomeis where the widget is displayed.
545 *
546 * @return array Array of taxonomies.
547 */
548 private function get_widget_taxonomies() {
549 $taxonomies = get_taxonomies(
550 array(
551 'public' => true,
552 'show_ui' => true,
553 )
554 );
555
556 /**
557 * Filter the taxonomies where we need to show the poster settings.
558 *
559 * @param array $taxonomies List of taxonomies to show settings.
560 */
561 return apply_filters( 'sharing_image_widget_taxonomies', array_values( $taxonomies ) );
562 }
563 }
564