PluginProbe
Sharing Image / 2.0.0
Sharing Image v2.0.0
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.0, at classes/class-widget.php

485 lines 11.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
56 /**
57 * Init metabox on post editing page.
58 */
59 public function init_metabox_widget() {
60 /**
61 * Easy way to hide metabox.
62 *
63 * @param bool $hide_metabox Set true to hide metabox.
64 */
65 $hide_metabox = apply_filters( 'sharing_image_hide_metabox', false );
66
67 if ( $hide_metabox ) {
68 return;
69 }
70
71 add_action( 'add_meta_boxes', array( $this, 'add_metabox' ) );
72 add_action( 'save_post', array( $this, 'save_metabox' ), 10, 2 );
73
74 // Add required assets and objects.
75 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_metabox_assets' ) );
76 }
77
78 /**
79 * Init widget on taxonomy term editing page.
80 */
81 public function init_taxonomy_widget() {
82 // Skip if the Premium is not active.
83 if ( ! $this->settings->is_premium_features() ) {
84 return;
85 }
86
87 $taxonomies = $this->get_widget_taxonomies();
88
89 foreach ( $taxonomies as $taxonomy ) {
90 // Display taxonomy term widget.
91 add_action( $taxonomy . '_edit_form', array( $this, 'display_widget' ), 10, 2 );
92
93 // Save taxonomy term meta.
94 add_action( 'edited_' . $taxonomy, array( $this, 'save_taxonomy' ) );
95
96 // Enqueue term assets.
97 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_taxonomy_assets' ) );
98 }
99 }
100
101 /**
102 * Add metabox to post editing page.
103 */
104 public function add_metabox() {
105 add_meta_box(
106 'sharing-image-metabox',
107 esc_html__( 'Sharing Image', 'sharing image' ),
108 array( $this, 'display_widget' ),
109 $this->get_metabox_post_types(),
110 'side'
111 );
112 }
113
114 /**
115 * Add metabox scripts and styles to admin page.
116 *
117 * @param string $hook_suffix The current admin page.
118 */
119 public function enqueue_metabox_assets( $hook_suffix ) {
120 if ( ! in_array( $hook_suffix, array( 'post.php', 'post-new.php' ), true ) ) {
121 return;
122 }
123
124 $screen = get_current_screen();
125
126 if ( ! in_array( $screen->post_type, $this->get_metabox_post_types(), true ) ) {
127 return;
128 }
129
130 $post = get_post();
131
132 // Get post meta for current post ID.
133 $meta = get_post_meta( $post->ID, self::WIDGET_META, true );
134
135 $this->enqueue_scripts( $this->create_script_object( $meta, 'metabox' ) );
136 $this->enqueue_styles();
137 }
138
139 /**
140 * Add widget scripts and styles to admin page.
141 *
142 * @param string $hook_suffix The current admin page.
143 */
144 public function enqueue_taxonomy_assets( $hook_suffix ) {
145 if ( 'term.php' !== $hook_suffix ) {
146 return;
147 }
148
149 $screen = get_current_screen();
150
151 if ( ! in_array( $screen->taxonomy, $this->get_widget_taxonomies(), true ) ) {
152 return;
153 }
154
155 // phpcs:disable WordPress.Security.NonceVerification
156 if ( ! isset( $_REQUEST['tag_ID'] ) ) {
157 return;
158 }
159
160 $term_id = absint( $_REQUEST['tag_ID'] );
161 // phpcs:enable WordPress.Security.NonceVerification
162
163 // Get term meta for current term ID.
164 $meta = get_term_meta( $term_id, self::WIDGET_META, true );
165
166 $this->enqueue_scripts( $this->create_script_object( $meta, 'taxonomy' ) );
167 $this->enqueue_styles();
168 }
169
170 /**
171 * Save metabox fields.
172 *
173 * @param int $post_id Post ID.
174 * @param WP_Post $post Post object.
175 */
176 public function save_metabox( $post_id, $post ) {
177 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
178 return;
179 }
180
181 if ( wp_is_post_revision( $post_id ) ) {
182 return;
183 }
184
185 if ( ! isset( $_POST['sharing_image_nonce'] ) ) {
186 return;
187 }
188
189 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
190 if ( ! wp_verify_nonce( $_POST['sharing_image_nonce'], basename( __FILE__ ) ) ) {
191 return;
192 }
193
194 if ( ! current_user_can( 'edit_post', $post_id ) ) {
195 return;
196 }
197
198 if ( ! isset( $_POST['sharing_image_picker'] ) ) {
199 return;
200 }
201
202 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
203 $meta = $this->sanitize_picker( wp_unslash( $_POST['sharing_image_picker'] ) );
204
205 /**
206 * Filters post meta on update.
207 *
208 * @param string $meta Updated post meta.
209 * @param string $post_id Post ID.
210 */
211 $meta = apply_filters( 'sharing_image_update_post_meta', $meta, $post_id );
212
213 // Update post meta.
214 update_post_meta( $post_id, self::WIDGET_META, $meta );
215 }
216
217 /**
218 * Save taxonomy fields.
219 *
220 * @param int $term_id Term ID.
221 */
222 public function save_taxonomy( $term_id ) {
223 if ( ! isset( $_POST['sharing_image_nonce'] ) ) {
224 return;
225 }
226
227 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
228 if ( ! wp_verify_nonce( $_POST['sharing_image_nonce'], basename( __FILE__ ) ) ) {
229 return;
230 }
231
232 if ( ! current_user_can( 'edit_term', $term_id ) ) {
233 return;
234 }
235
236 if ( ! isset( $_POST['sharing_image_picker'] ) ) {
237 return;
238 }
239
240 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
241 $meta = $this->sanitize_picker( wp_unslash( $_POST['sharing_image_picker'] ) );
242
243 /**
244 * Filters term meta on update.
245 *
246 * @param string $meta Updated term meta.
247 * @param string $term_id Term ID.
248 */
249 $meta = apply_filters( 'sharing_image_update_term_meta', $meta, $term_id );
250
251 update_term_meta( $term_id, self::WIDGET_META, $meta );
252 }
253
254 /**
255 * Display widget.
256 */
257 public function display_widget() {
258 include_once SHARING_IMAGE_DIR . 'templates/widget.php';
259
260 /**
261 * Fires on widget template including.
262 */
263 do_action( 'sharing_image_widget' );
264 }
265
266 /**
267 * Handle widget AJAX requests.
268 */
269 public function handle_ajax_requests() {
270 $actions = array(
271 'generate' => 'generate_poster',
272 );
273
274 foreach ( $actions as $key => $method ) {
275 $action = 'sharing_image_' . $key;
276
277 if ( method_exists( $this, $method ) ) {
278 add_action( 'wp_ajax_' . $action, array( $this, $method ) );
279 }
280 }
281 }
282
283 /**
284 * Generate poster by AJAX request.
285 */
286 public function generate_poster() {
287 $check = check_ajax_referer( basename( __FILE__ ), 'sharing_image_nonce', false );
288
289 if ( false === $check ) {
290 wp_send_json_error( __( 'Invalid security token. Reload the page and retry.', 'sharing-image' ), 403 );
291 }
292
293 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
294 $picker = $this->sanitize_picker( wp_unslash( $_POST['sharing_image_picker'] ) );
295
296 // Compose new poster.
297 $poster = ( new Generator() )->compose( $picker );
298
299 if ( is_wp_error( $poster ) ) {
300 wp_send_json_error( $poster->get_error_message(), 400 );
301 }
302
303 wp_send_json_success( $poster );
304 }
305
306 /**
307 * Enqueue widget styles.
308 */
309 private function enqueue_styles() {
310 wp_enqueue_style(
311 'sharing-image-widget',
312 SHARING_IMAGE_URL . 'assets/styles/widget.css',
313 array(),
314 SHARING_IMAGE_VERSION,
315 'all'
316 );
317 }
318
319 /**
320 * Enqueue widget scripts.
321 *
322 * @param array $object Widget data object.
323 */
324 private function enqueue_scripts( $object ) {
325 wp_enqueue_media();
326
327 wp_enqueue_script(
328 'sharing-image-widget',
329 SHARING_IMAGE_URL . 'assets/scripts/widget.js',
330 array( 'wp-i18n', 'wp-polyfill-formdata' ),
331 SHARING_IMAGE_VERSION,
332 true
333 );
334
335 wp_set_script_translations( 'sharing-image-settings', 'sharing-image' );
336
337 // Add widget script object.
338 wp_localize_script( 'sharing-image-widget', 'sharingImageWidget', $object );
339 }
340
341 /**
342 * Sanitize picker widget data before saving.
343 *
344 * @param array $picker Widget POST data.
345
346 * @return array Sanitized picker fields.
347 */
348 private function sanitize_picker( $picker ) {
349 $sanitized = array();
350
351 if ( isset( $picker['poster'] ) ) {
352 $sanitized['poster'] = sanitize_text_field( $picker['poster'] );
353 }
354
355 if ( ! empty( $picker['width'] ) ) {
356 $sanitized['width'] = absint( $picker['width'] );
357 }
358
359 if ( ! empty( $picker['height'] ) ) {
360 $sanitized['height'] = absint( $picker['height'] );
361 }
362
363 $template = 0;
364
365 if ( isset( $picker['template'] ) ) {
366 $template = absint( $picker['template'] );
367
368 if ( count( $this->settings->get_templates() ) <= $template ) {
369 $template = 0;
370 }
371 }
372
373 $sanitized['template'] = $template;
374
375 if ( isset( $picker['fieldset'] ) ) {
376 $fieldset = $picker['fieldset'];
377
378 foreach ( $fieldset as $key => $fields ) {
379 $sanitized['fieldset'][ $key ] = $this->sanitize_fieldset( $fields );
380 }
381 }
382
383 /**
384 * Filters widget picker sanitized fields.
385 *
386 * @param array $sanitized List of sanitized picker fields.
387 * @param array $picker List of picker fields before sanitization.
388 */
389 return apply_filters( 'sharing_image_sanitize_picker', $sanitized, $picker );
390 }
391
392 /**
393 * Sanitize picker widget fieldset list.
394 *
395 * @param array $fields Fieldset widget list.
396 *
397 * @return array Sanitized fieldset data.
398 */
399 public function sanitize_fieldset( $fields ) {
400 $sanitized = array();
401
402 if ( ! empty( $fields['captions'] ) && is_array( $fields['captions'] ) ) {
403 $sanitized['captions'] = array_map( 'sanitize_textarea_field', $fields['captions'] );
404 }
405
406 if ( ! empty( $fields['attachment'] ) ) {
407 $sanitized['attachment'] = absint( $fields['attachment'] );
408 }
409
410 return $sanitized;
411 }
412
413 /**
414 * Create script object to inject with widget.
415 *
416 * @param array $meta Term or Post meta data.
417 * @param string $context Widget context. For example: metabox or taxonomy.
418
419 * @return array Filtered widget script object.
420 */
421 private function create_script_object( $meta, $context ) {
422 $object = array(
423 'meta' => $meta,
424 'nonce' => wp_create_nonce( basename( __FILE__ ) ),
425 'context' => $context,
426
427 'links' => array(
428 'uploads' => esc_url( admin_url( 'upload.php' ) ),
429 ),
430
431 'templates' => $this->settings->get_templates(),
432 );
433
434 /**
435 * Filter widget script object.
436 *
437 * @param array $object Array of widget script object.
438 */
439 return apply_filters( 'sharing_image_widget_object', $object );
440 }
441
442 /**
443 * Get an array of post types where the metabox is displayed.
444 *
445 * @return array Array of post types.
446 */
447 private function get_metabox_post_types() {
448 $post_types = get_post_types(
449 array(
450 'public' => true,
451 )
452 );
453
454 unset( $post_types['attachment'] );
455
456 /**
457 * Filter widget post types.
458 *
459 * @param array $post_types Array of post types for which the metabox is displayed.
460 */
461 return apply_filters( 'sharing_image_metabox_post_types', array_values( $post_types ) );
462 }
463
464 /**
465 * Get an array of taxonomeis where the widget is displayed.
466 *
467 * @return array Array of taxonomies.
468 */
469 private function get_widget_taxonomies() {
470 $taxonomies = get_taxonomies(
471 array(
472 'public' => true,
473 'show_ui' => true,
474 )
475 );
476
477 /**
478 * Filter the taxonomies where we need to show the poster settings.
479 *
480 * @param array $taxonomies List of taxonomies to show settings.
481 */
482 return apply_filters( 'sharing_image_widget_taxonomies', array_values( $taxonomies ) );
483 }
484 }
485