PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 All 508 releases
← All changes | modules/widgets/gallery.php +526 -0 16.2-beta → 16.3 View file →
@@ -1,0 +1,526 @@
1 +<?php // phpcs:ignore eWordPress.Files.FileName.InvalidClassFileName
2 +/**
3 + * Module Name: Gallery widget
4 + *
5 + * @package automattic/jetpack
6 + */
7 +
8 +// phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- TODO: Move classes to appropriately-named class files.
9 +
10 +use Automattic\Jetpack\Assets;
11 +use Automattic\Jetpack\Image_CDN\Image_CDN_Core;
12 +
13 +if ( ! defined( 'ABSPATH' ) ) {
14 + exit( 0 );
15 +}
16 +
17 +/**
18 + * Jetpack_Gallery_Widget main class.
19 + */
20 +class Jetpack_Gallery_Widget extends WP_Widget {
21 + const THUMB_SIZE = 45;
22 + const DEFAULT_WIDTH = 265;
23 +
24 + /**
25 + * The width of the gallery widget.
26 + * May be customized by the 'gallery_widget_content_width' filter.
27 + *
28 + * @var int
29 + */
30 + protected $instance_width;
31 +
32 + /**
33 + * Jetpack_Gallery_Widget constructor.
34 + */
35 + public function __construct() {
36 + $widget_ops = array(
37 + 'classname' => 'widget-gallery',
38 + 'description' => __( 'Display a photo gallery or slideshow', 'jetpack' ),
39 + 'customize_selective_refresh' => true,
40 + );
41 +
42 + add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
43 +
44 + parent::__construct(
45 + 'gallery',
46 + /** This filter is documented in modules/widgets/facebook-likebox.php */
47 + apply_filters( 'jetpack_widget_name', __( 'Gallery', 'jetpack' ) ),
48 + $widget_ops
49 + );
50 +
51 + if ( is_customize_preview() ) {
52 + add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_scripts' ) );
53 +
54 + if ( class_exists( 'Jetpack_Tiled_Gallery' ) ) {
55 + add_action( 'wp_enqueue_scripts', array( 'Jetpack_Tiled_Gallery', 'default_scripts_and_styles' ) );
56 + }
57 +
58 + if ( class_exists( 'Jetpack_Slideshow_Shortcode' ) ) {
59 + $slideshow = new Jetpack_Slideshow_Shortcode();
60 + add_action( 'wp_enqueue_scripts', array( $slideshow, 'enqueue_scripts' ) );
61 + }
62 +
63 + if ( class_exists( 'Jetpack_Carousel' ) ) {
64 + $carousel = new Jetpack_Carousel();
65 + add_action( 'wp_enqueue_scripts', array( $carousel, 'enqueue_assets' ) );
66 + }
67 + }
68 + }
69 +
70 + /**
71 + * Display the widget.
72 + *
73 + * @param array $args Display arguments including before_title, after_title, before_widget, and after_widget.
74 + * @param array $instance The settings for the particular instance of the widget.
75 + */
76 + public function widget( $args, $instance ) {
77 + $instance = wp_parse_args( (array) $instance, $this->defaults() );
78 +
79 + $this->enqueue_frontend_scripts();
80 +
81 + $before_widget = $args['before_widget'] ?? '';
82 + $before_title = $args['before_title'] ?? '';
83 + $after_title = $args['after_title'] ?? '';
84 + $after_widget = $args['after_widget'] ?? '';
85 +
86 + $instance['attachments'] = $this->get_attachments( $instance );
87 +
88 + $classes = array();
89 +
90 + $classes[] = 'widget-gallery-' . $instance['type'];
91 +
92 + /*
93 + * Due to a bug in the carousel plugin,
94 + * carousels will be triggered for all tiled galleries that exist on a page with other tiled galleries,
95 + * regardless of whether or not the widget was set to Carousel mode.
96 + * The onClick selector is simply too broad, since it was not written with widgets in mind.
97 + * This special class prevents that behavior, via an override handler in gallery.js.
98 + */
99 + if ( 'carousel' !== $instance['link'] && 'slideshow' !== $instance['type'] ) {
100 + $classes[] = 'no-carousel';
101 + } else {
102 + $classes[] = 'carousel';
103 + }
104 +
105 + $classes = implode( ' ', $classes );
106 +
107 + if ( 'carousel' === $instance['link'] ) {
108 + require_once plugin_dir_path( realpath( __DIR__ . '/../carousel/jetpack-carousel.php' ) ) . 'jetpack-carousel.php';
109 +
110 + if ( class_exists( 'Jetpack_Carousel' ) ) {
111 + // Create new carousel so we can use the enqueue_assets() method. Not ideal, but there is a decent amount
112 + // of logic in that method that shouldn't be duplicated.
113 + $carousel = new Jetpack_Carousel();
114 +
115 + $carousel->enqueue_assets();
116 + }
117 + }
118 +
119 + echo $before_widget . "\n"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
120 +
121 + /** This filter is documented in core/src/wp-includes/default-widgets.php */
122 + $title = apply_filters( 'widget_title', $instance['title'] );
123 +
124 + if ( $title ) {
125 + echo $before_title . $title . $after_title . "\n"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
126 + }
127 +
128 + echo '<div class="' . esc_attr( $classes ) . '">' . "\n";
129 +
130 + $method = $instance['type'] . '_widget';
131 +
132 + /**
133 + * Allow the width of a gallery to be altered by themes or other code.
134 + *
135 + * @module widgets
136 + *
137 + * @since 2.5.0
138 + *
139 + * @param int self::DEFAULT_WIDTH Default gallery width. Default is 265.
140 + * @param string $args Display arguments including before_title, after_title, before_widget, and after_widget.
141 + * @param array $instance The settings for the particular instance of the widget.
142 + */
143 + $this->instance_width = apply_filters( 'gallery_widget_content_width', self::DEFAULT_WIDTH, $args, $instance );
144 +
145 + // Register a filter to modify the tiled_gallery_content_width, so Jetpack_Tiled_Gallery
146 + // can appropriately size the tiles.
147 + add_filter( 'tiled_gallery_content_width', array( $this, 'tiled_gallery_content_width' ) );
148 +
149 + if ( method_exists( $this, $method ) ) {
150 + echo $this->$method( $args, $instance ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
151 + }
152 +
153 + // Remove the stored $instance_width, as it is no longer needed.
154 + $this->instance_width = null;
155 +
156 + // Remove the filter, so any Jetpack_Tiled_Gallery in a post is not affected.
157 + remove_filter( 'tiled_gallery_content_width', array( $this, 'tiled_gallery_content_width' ) );
158 +
159 + echo "\n" . '</div>'; // .widget-gallery-$type
160 +
161 + echo "\n" . $after_widget; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
162 +
163 + /** This action is documented in modules/widgets/gravatar-profile.php */
164 + do_action( 'jetpack_stats_extra', 'widget_view', 'gallery' );
165 + }
166 +
167 + /**
168 + * Fetch the images attached to the gallery Widget
169 + *
170 + * @param array $instance The Widget instance for which you'd like attachments.
171 + * @return array Array of attachment objects for the Widget in $instance
172 + */
173 + public function get_attachments( $instance ) {
174 + $ids = explode( ',', $instance['ids'] );
175 +
176 + if ( isset( $instance['random'] ) && 'on' === $instance['random'] ) {
177 + shuffle( $ids );
178 + }
179 +
180 + $attachments_query = new WP_Query(
181 + array(
182 + 'post__in' => $ids,
183 + 'post_status' => 'inherit',
184 + 'post_type' => 'attachment',
185 + 'post_mime_type' => 'image',
186 + 'posts_per_page' => -1,
187 + 'orderby' => 'post__in',
188 + )
189 + );
190 +
191 + $attachments = $attachments_query->get_posts();
192 +
193 + wp_reset_postdata();
194 +
195 + return $attachments;
196 + }
197 +
198 + /**
199 + * Generate HTML for a rectangular, tiled Widget
200 + *
201 + * @param array $args Display arguments including before_title, after_title, before_widget, and after_widget.
202 + * @param array $instance The Widget instance to generate HTML for.
203 + * @return string String of HTML representing a rectangular gallery
204 + */
205 + public function rectangular_widget( $args, $instance ) {
206 + if ( ! class_exists( 'Jetpack_Tiled_Gallery' )
207 + && ! class_exists( 'Jetpack_Tiled_Gallery_Layout_Rectangular' ) ) {
208 + return;
209 + }
210 +
211 + Jetpack_Tiled_Gallery::default_scripts_and_styles();
212 +
213 + $layout = new Jetpack_Tiled_Gallery_Layout_Rectangular( $instance['attachments'], $instance['link'], false, 3 );
214 + return $layout->HTML();
215 + }
216 +
217 + /**
218 + * Generate HTML for a square (grid style) Widget
219 + *
220 + * @param array $args Display arguments including before_title, after_title, before_widget, and after_widget.
221 + * @param array $instance The Widget instance to generate HTML for.
222 + * @return string String of HTML representing a square gallery
223 + */
224 + public function square_widget( $args, $instance ) {
225 + if ( ! class_exists( 'Jetpack_Tiled_Gallery' )
226 + && ! class_exists( 'Jetpack_Tiled_Gallery_Layout_Square' ) ) {
227 + return;
228 + }
229 +
230 + Jetpack_Tiled_Gallery::default_scripts_and_styles();
231 +
232 + $layout = new Jetpack_Tiled_Gallery_Layout_Square( $instance['attachments'], $instance['link'], false, 3 );
233 + return $layout->HTML();
234 + }
235 +
236 + /**
237 + * Generate HTML for a circular (grid style) Widget
238 + *
239 + * @param array $args Display arguments including before_title, after_title, before_widget, and after_widget.
240 + * @param array $instance The Widget instance to generate HTML for.
241 + * @return string String of HTML representing a circular gallery
242 + */
243 + public function circle_widget( $args, $instance ) {
244 + if ( ! class_exists( 'Jetpack_Tiled_Gallery' )
245 + && ! class_exists( 'Jetpack_Tiled_Gallery_Layout_Circle' ) ) {
246 + return;
247 + }
248 +
249 + Jetpack_Tiled_Gallery::default_scripts_and_styles();
250 +
251 + $layout = new Jetpack_Tiled_Gallery_Layout_Circle( $instance['attachments'], $instance['link'], false, 3 );
252 + return $layout->HTML();
253 + }
254 +
255 + /**
256 + * Generate HTML for a slideshow Widget
257 + *
258 + * @todo Is slideshow_widget() still used?
259 + *
260 + * @param array $args Display arguments including before_title, after_title, before_widget, and after_widget.
261 + * @param array $instance The Widget instance to generate HTML for.
262 + * @return string String of HTML representing a slideshow gallery
263 + */
264 + public function slideshow_widget( $args, $instance ) {
265 + global $content_width;
266 +
267 + require_once plugin_dir_path( realpath( __DIR__ . '/../shortcodes/slideshow.php' ) ) . 'slideshow.php';
268 +
269 + if ( ! class_exists( 'Jetpack_Slideshow_Shortcode' ) ) {
270 + return;
271 + }
272 +
273 + if ( count( $instance['attachments'] ) < 1 ) {
274 + return;
275 + }
276 +
277 + $slideshow = new Jetpack_Slideshow_Shortcode();
278 +
279 + $slideshow->enqueue_scripts();
280 +
281 + $gallery_instance = 'widget-' . $args['widget_id'];
282 +
283 + $gallery = array();
284 +
285 + foreach ( $instance['attachments'] as $attachment ) {
286 + $attachment_image_src = wp_get_attachment_image_src( $attachment->ID, 'full' );
287 + $attachment_image_src = Image_CDN_Core::cdn_url( $attachment_image_src[0], array( 'w' => $this->instance_width ) ); /** [url, width, height] */
288 +
289 + $caption = wptexturize( wp_strip_all_tags( $attachment->post_excerpt ) );
290 +
291 + $gallery[] = (object) array(
292 + 'src' => (string) esc_url_raw( $attachment_image_src ),
293 + 'id' => (string) $attachment->ID,
294 + 'caption' => (string) $caption,
295 + );
296 + }
297 +
298 + $max_width = (int) get_option( 'large_size_w' );
299 + $max_height = 175;
300 +
301 + if ( (int) $content_width > 0 ) {
302 + $max_width = min( (int) $content_width, $max_width );
303 + }
304 +
305 + $color = Jetpack_Options::get_option( 'slideshow_background_color', 'black' );
306 + $js_attr = array(
307 + 'gallery' => $gallery,
308 + 'selector' => $gallery_instance,
309 + 'width' => $max_width,
310 + 'height' => $max_height,
311 + 'trans' => 'fade',
312 + 'color' => $color,
313 + 'autostart' => true,
314 + );
315 +
316 + $html = $slideshow->slideshow_js( $js_attr );
317 +
318 + return $html;
319 + }
320 +
321 + /**
322 + * Used to adjust the content width of Jetpack_Tiled_Gallery's in sidebars
323 + *
324 + * $this->instance_width is filtered in widget() and this filter is added then removed in widget()
325 + *
326 + * @return int The filtered width
327 + */
328 + public function tiled_gallery_content_width() {
329 + return $this->instance_width;
330 + }
331 +
332 + /**
333 + * Outputs the widget settings form.
334 + *
335 + * @html-template-var array $instance
336 + * @html-template-var array<string,array<string|int,string|int>> $allowed_values
337 + *
338 + * @param array $instance Current settings.
339 + * @return string|void
340 + */
341 + public function form( $instance ) {
342 + $defaults = $this->defaults();
343 + $allowed_values = $this->allowed_values(); // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- Used in included form template.
344 +
345 + $instance = wp_parse_args( (array) $instance, $defaults );
346 +
347 + include __DIR__ . '/gallery/templates/form.php';
348 + }
349 +
350 + /**
351 + * Save the widget options.
352 + *
353 + * @param array $new_instance The new instance options.
354 + * @param array $old_instance The old instance options.
355 + * @return array The saved options.
356 + */
357 + public function update( $new_instance, $old_instance ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
358 + $instance = $this->sanitize( $new_instance );
359 +
360 + return $instance;
361 + }
362 +
363 + /**
364 + * Sanitize the $instance's values to the set of allowed values. If a value is not acceptable,
365 + * it is set to its default.
366 + *
367 + * Helps keep things nice and secure by listing only allowed values.
368 + *
369 + * @param array $instance The Widget instance to sanitize values for.
370 + * @return array $instance The Widget instance with values sanitized
371 + */
372 + public function sanitize( $instance ) {
373 + $allowed_values = $this->allowed_values();
374 + $defaults = $this->defaults();
375 +
376 + foreach ( $instance as $key => $value ) {
377 + if ( ! is_scalar( $value ) ) {
378 + // $instance may hold an Array value type for the Jetpack widget visibility feature.
379 + continue;
380 + }
381 +
382 + $value = trim( $value );
383 +
384 + if ( isset( $allowed_values[ $key ] ) && $allowed_values[ $key ] && ! array_key_exists( $value, $allowed_values[ $key ] ) ) {
385 + $instance[ $key ] = $defaults[ $key ];
386 + } else {
387 + $instance[ $key ] = sanitize_text_field( $value );
388 + }
389 + }
390 +
391 + return $instance;
392 + }
393 +
394 + /**
395 + * Return a multi-dimensional array of allowed values (and their labels) for all widget form
396 + * elements
397 + *
398 + * To allow all values on an input, omit it from the returned array
399 + *
400 + * @return array Array of allowed values for each option
401 + */
402 + public function allowed_values() {
403 + $max_columns = 5;
404 +
405 + // Create an associative array of allowed column values. This just automates the generation of
406 + // column <option>s, from 1 to $max_columns.
407 + $allowed_columns = array_combine( range( 1, $max_columns ), range( 1, $max_columns ) );
408 +
409 + return array(
410 + 'type' => array(
411 + 'rectangular' => __( 'Tiles', 'jetpack' ),
412 + 'square' => __( 'Square Tiles', 'jetpack' ),
413 + 'circle' => __( 'Circles', 'jetpack' ),
414 + 'slideshow' => __( 'Slideshow', 'jetpack' ),
415 + ),
416 + 'columns' => $allowed_columns,
417 + 'link' => array(
418 + 'carousel' => __( 'Carousel', 'jetpack' ),
419 + 'post' => __( 'Attachment Page', 'jetpack' ),
420 + 'file' => __( 'Media File', 'jetpack' ),
421 + ),
422 + );
423 + }
424 +
425 + /**
426 + * Return an associative array of default values
427 + *
428 + * These values are used in new widgets as well as when sanitizing input. If a given value is not allowed,
429 + * as defined in allowed_values(), that input is set to the default value defined here.
430 + *
431 + * @return array Array of default values for the Widget's options
432 + */
433 + public function defaults() {
434 + return array(
435 + 'title' => '',
436 + 'type' => 'rectangular',
437 + 'ids' => '',
438 + 'columns' => 3,
439 + 'link' => 'carousel',
440 + );
441 + }
442 +
443 + /**
444 + * Enqueue frontend scripts.
445 + */
446 + public function enqueue_frontend_scripts() {
447 + wp_register_script(
448 + 'gallery-widget',
449 + Assets::get_file_url_for_environment(
450 + '_inc/build/widgets/gallery/js/gallery.min.js',
451 + 'modules/widgets/gallery/js/gallery.js'
452 + ),
453 + array( 'jquery' ),
454 + JETPACK__VERSION,
455 + false
456 + );
457 +
458 + wp_enqueue_script( 'gallery-widget' );
459 + }
460 +
461 + /**
462 + * Enqueue admin scripts and styles.
463 + */
464 + public function enqueue_admin_scripts() {
465 + global $pagenow;
466 +
467 + if ( 'widgets.php' === $pagenow || 'customize.php' === $pagenow ) {
468 + wp_enqueue_media();
469 +
470 + wp_enqueue_script(
471 + 'gallery-widget-admin',
472 + Assets::get_file_url_for_environment(
473 + '_inc/build/widgets/gallery/js/admin.min.js',
474 + 'modules/widgets/gallery/js/admin.js'
475 + ),
476 + array(
477 + 'jquery',
478 + 'media-models',
479 + 'media-views',
480 + ),
481 + '20150501',
482 + false
483 + );
484 +
485 + $js_settings = array(
486 + 'thumbSize' => self::THUMB_SIZE,
487 + );
488 +
489 + wp_localize_script( 'gallery-widget-admin', '_wpGalleryWidgetAdminSettings', $js_settings );
490 + wp_enqueue_style(
491 + 'gallery-widget-admin',
492 + plugins_url( '/gallery/css/admin.css', __FILE__ ),
493 + array(),
494 + JETPACK__VERSION
495 + );
496 + wp_style_add_data( 'gallery-widget-admin', 'rtl', 'replace' );
497 + }
498 + }
499 +}
500 +
501 +add_action( 'widgets_init', 'jetpack_gallery_widget_init' );
502 +
503 +/**
504 + * Jetpack Gallery widget init; the widget is conditionally registered.
505 + */
506 +function jetpack_gallery_widget_init() {
507 + /**
508 + * Allow the Gallery Widget to be enabled even when Core supports the Media Gallery Widget
509 + *
510 + * @module widgets
511 + *
512 + * @since 5.5.0
513 + *
514 + * @param bool false Whether to force-enable the gallery widget
515 + */
516 + if (
517 + ! apply_filters( 'jetpack_force_enable_gallery_widget', false )
518 + && class_exists( 'WP_Widget_Media_Gallery' )
519 + && Jetpack_Options::get_option( 'gallery_widget_migration' )
520 + ) {
521 + return;
522 + }
523 + if ( ! method_exists( 'Jetpack', 'is_module_active' ) || Jetpack::is_module_active( 'tiled-gallery' ) ) {
524 + register_widget( 'Jetpack_Gallery_Widget' );
525 + }
526 +}