| 1 |
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName |
| 2 |
|
| 3 |
use Automattic\Jetpack\Assets; |
| 4 |
use Automattic\Jetpack\Image_CDN\Image_CDN; |
| 5 |
use Automattic\Jetpack\Status; |
| 6 |
|
| 7 |
if ( ! defined( 'ABSPATH' ) ) { |
| 8 |
exit( 0 ); |
| 9 |
} |
| 10 |
|
| 11 |
// Include the class file containing methods for rounding constrained array elements. |
| 12 |
// Here the constrained array element is the dimension of a row, group or an image in the tiled gallery. |
| 13 |
require_once __DIR__ . '/math/class-constrained-array-rounding.php'; |
| 14 |
|
| 15 |
// Layouts |
| 16 |
require_once __DIR__ . '/tiled-gallery/tiled-gallery-rectangular.php'; |
| 17 |
require_once __DIR__ . '/tiled-gallery/tiled-gallery-square.php'; |
| 18 |
require_once __DIR__ . '/tiled-gallery/tiled-gallery-circle.php'; |
| 19 |
|
| 20 |
/** |
| 21 |
* Jetpack tiled gallery class. |
| 22 |
*/ |
| 23 |
class Jetpack_Tiled_Gallery { |
| 24 |
/** |
| 25 |
* Shortcode attributes. |
| 26 |
* |
| 27 |
* @var array |
| 28 |
*/ |
| 29 |
public $atts; |
| 30 |
|
| 31 |
/** |
| 32 |
* Text direction (right or left). |
| 33 |
* |
| 34 |
* @var string |
| 35 |
*/ |
| 36 |
public $float; |
| 37 |
|
| 38 |
/** |
| 39 |
* Supported gallery design types. |
| 40 |
* |
| 41 |
* @var array |
| 42 |
*/ |
| 43 |
private static $talaveras = array( 'rectangular', 'square', 'circle', 'rectangle', 'columns' ); |
| 44 |
|
| 45 |
/** |
| 46 |
* Class constructor. |
| 47 |
*/ |
| 48 |
public function __construct() { |
| 49 |
add_action( 'admin_init', array( $this, 'settings_api_init' ) ); |
| 50 |
add_filter( 'jetpack_gallery_types', array( $this, 'jetpack_gallery_types' ), 9 ); |
| 51 |
add_filter( 'jetpack_default_gallery_type', array( $this, 'jetpack_default_gallery_type' ) ); |
| 52 |
} |
| 53 |
|
| 54 |
/** |
| 55 |
* Check whether tiling is enabled. |
| 56 |
* |
| 57 |
* @return bool |
| 58 |
*/ |
| 59 |
public function tiles_enabled() { |
| 60 |
return '' !== Jetpack_Options::get_option_and_ensure_autoload( 'tiled_galleries', '' ); |
| 61 |
} |
| 62 |
|
| 63 |
/** |
| 64 |
* Set attributes. |
| 65 |
* |
| 66 |
* @param array $atts - the attributes. |
| 67 |
*/ |
| 68 |
public function set_atts( $atts ) { |
| 69 |
global $post; |
| 70 |
|
| 71 |
$this->atts = shortcode_atts( |
| 72 |
array( |
| 73 |
'order' => 'ASC', |
| 74 |
'orderby' => 'menu_order ID', |
| 75 |
'id' => $post->ID ?? 0, |
| 76 |
'include' => '', |
| 77 |
'exclude' => '', |
| 78 |
'type' => '', |
| 79 |
'grayscale' => false, |
| 80 |
'link' => '', |
| 81 |
'columns' => 3, |
| 82 |
), |
| 83 |
$atts, |
| 84 |
'gallery' |
| 85 |
); |
| 86 |
|
| 87 |
$this->atts['id'] = (int) $this->atts['id']; |
| 88 |
$this->float = is_rtl() ? 'right' : 'left'; |
| 89 |
|
| 90 |
// Default to rectangular is tiled galleries are checked |
| 91 |
if ( $this->tiles_enabled() && ( ! $this->atts['type'] || 'default' === $this->atts['type'] ) ) { |
| 92 |
/** This filter is already documented in class-jetpack-gallery-settings.php */ |
| 93 |
$this->atts['type'] = apply_filters( 'jetpack_default_gallery_type', 'rectangular' ); |
| 94 |
} |
| 95 |
|
| 96 |
if ( ! $this->atts['orderby'] ) { |
| 97 |
$this->atts['orderby'] = sanitize_sql_orderby( $this->atts['orderby'] ); |
| 98 |
if ( ! $this->atts['orderby'] ) { |
| 99 |
$this->atts['orderby'] = 'menu_order ID'; |
| 100 |
} |
| 101 |
} |
| 102 |
|
| 103 |
if ( 'rand' === strtolower( $this->atts['order'] ) ) { |
| 104 |
$this->atts['orderby'] = 'rand'; |
| 105 |
} |
| 106 |
|
| 107 |
// We shouldn't have more than 20 columns. |
| 108 |
if ( ! is_numeric( $this->atts['columns'] ) || 20 < $this->atts['columns'] ) { |
| 109 |
$this->atts['columns'] = 3; |
| 110 |
} |
| 111 |
} |
| 112 |
|
| 113 |
/** |
| 114 |
* Get the media attachments. |
| 115 |
* |
| 116 |
* @return WP_Post[] |
| 117 |
*/ |
| 118 |
public function get_attachments() { |
| 119 |
$atts = $this->atts; |
| 120 |
|
| 121 |
if ( ! empty( $atts['include'] ) ) { |
| 122 |
$include = preg_replace( '/[^0-9,]+/', '', $atts['include'] ); |
| 123 |
$_attachments = get_posts( |
| 124 |
array( |
| 125 |
'include' => $include, |
| 126 |
'post_status' => 'inherit', |
| 127 |
'post_type' => 'attachment', |
| 128 |
'post_mime_type' => 'image', |
| 129 |
'order' => $atts['order'], |
| 130 |
'orderby' => $atts['orderby'], |
| 131 |
'suppress_filters' => false, |
| 132 |
) |
| 133 |
); |
| 134 |
|
| 135 |
$attachments = array(); |
| 136 |
foreach ( $_attachments as $key => $val ) { |
| 137 |
$attachments[ $val->ID ] = $_attachments[ $key ]; |
| 138 |
} |
| 139 |
} elseif ( 0 === $atts['id'] ) { |
| 140 |
/* |
| 141 |
* Should NEVER Happen but infinite_scroll_load_other_plugins_scripts means it does |
| 142 |
* Querying with post_parent == 0 can generate stupidly memcache sets |
| 143 |
* on sites with 10000's of unattached attachments as get_children puts every post in the cache. |
| 144 |
* TODO Fix this properly. |
| 145 |
*/ |
| 146 |
$attachments = array(); |
| 147 |
} elseif ( ! empty( $atts['exclude'] ) ) { |
| 148 |
$exclude = preg_replace( '/[^0-9,]+/', '', $atts['exclude'] ); |
| 149 |
$attachments = get_children( |
| 150 |
array( |
| 151 |
'post_parent' => $atts['id'], |
| 152 |
'exclude' => $exclude, |
| 153 |
'post_status' => 'inherit', |
| 154 |
'post_type' => 'attachment', |
| 155 |
'post_mime_type' => 'image', |
| 156 |
'order' => $atts['order'], |
| 157 |
'orderby' => $atts['orderby'], |
| 158 |
'suppress_filters' => false, |
| 159 |
) |
| 160 |
); |
| 161 |
} else { |
| 162 |
$attachments = get_children( |
| 163 |
array( |
| 164 |
'post_parent' => $atts['id'], |
| 165 |
'post_status' => 'inherit', |
| 166 |
'post_type' => 'attachment', |
| 167 |
'post_mime_type' => 'image', |
| 168 |
'order' => $atts['order'], |
| 169 |
'orderby' => $atts['orderby'], |
| 170 |
'suppress_filters' => false, |
| 171 |
) |
| 172 |
); |
| 173 |
} |
| 174 |
return $attachments; |
| 175 |
} |
| 176 |
|
| 177 |
/** |
| 178 |
* Enqueue the default scripts and styles. |
| 179 |
*/ |
| 180 |
public static function default_scripts_and_styles() { |
| 181 |
wp_enqueue_script( |
| 182 |
'tiled-gallery', |
| 183 |
Assets::get_file_url_for_environment( |
| 184 |
'_inc/build/tiled-gallery/tiled-gallery/tiled-gallery.min.js', |
| 185 |
'modules/tiled-gallery/tiled-gallery/tiled-gallery.js' |
| 186 |
), |
| 187 |
array(), |
| 188 |
JETPACK__VERSION, |
| 189 |
array( |
| 190 |
'in_footer' => true, |
| 191 |
'strategy' => 'defer', |
| 192 |
) |
| 193 |
); |
| 194 |
wp_enqueue_style( 'tiled-gallery', plugins_url( 'tiled-gallery/tiled-gallery.css', __FILE__ ), array(), '2023-08-21' ); |
| 195 |
wp_style_add_data( 'tiled-gallery', 'rtl', 'replace' ); |
| 196 |
} |
| 197 |
|
| 198 |
/** |
| 199 |
* The gallery shortcode. |
| 200 |
* |
| 201 |
* @param mixed $val - the value. |
| 202 |
* @param array $atts - the attributes. |
| 203 |
* |
| 204 |
* @return string |
| 205 |
*/ |
| 206 |
public function gallery_shortcode( $val, $atts ) { |
| 207 |
if ( ! empty( $val ) ) { // something else is overriding post_gallery, like a custom VIP shortcode |
| 208 |
return $val; |
| 209 |
} |
| 210 |
|
| 211 |
$this->set_atts( $atts ); |
| 212 |
|
| 213 |
$attachments = $this->get_attachments(); |
| 214 |
if ( empty( $attachments ) ) { |
| 215 |
return ''; |
| 216 |
} |
| 217 |
|
| 218 |
if ( is_feed() || defined( 'IS_HTML_EMAIL' ) ) { |
| 219 |
return ''; |
| 220 |
} |
| 221 |
|
| 222 |
/** |
| 223 |
* Filters the permissible Tiled Gallery types. |
| 224 |
* |
| 225 |
* @module tiled-gallery |
| 226 |
* |
| 227 |
* @since 3.7.0 |
| 228 |
* |
| 229 |
* @param array Array of allowed types. Default: 'rectangular', 'square', 'circle', 'rectangle', 'columns'. |
| 230 |
*/ |
| 231 |
$talaveras = apply_filters( 'jetpack_tiled_gallery_types', self::$talaveras ); |
| 232 |
|
| 233 |
if ( in_array( $this->atts['type'], $talaveras, true ) ) { |
| 234 |
// Enqueue styles and scripts |
| 235 |
self::default_scripts_and_styles(); |
| 236 |
|
| 237 |
// Generate gallery HTML |
| 238 |
$gallery_class = 'Jetpack_Tiled_Gallery_Layout_' . ucfirst( $this->atts['type'] ); |
| 239 |
$gallery = new $gallery_class( $attachments, $this->atts['link'], $this->atts['grayscale'], (int) $this->atts['columns'] ); |
| 240 |
$gallery_html = $gallery->HTML(); |
| 241 |
|
| 242 |
if ( $gallery_html && class_exists( 'Jetpack' ) && class_exists( Image_CDN::class ) ) { |
| 243 |
// Tiled Galleries in Jetpack require that Photon be active. |
| 244 |
// If it's not active, run it just on the gallery output. |
| 245 |
if ( ! Image_CDN::is_enabled() && ! ( new Status() )->is_offline_mode() ) { |
| 246 |
$gallery_html = Image_CDN::filter_the_content( $gallery_html ); |
| 247 |
} |
| 248 |
} |
| 249 |
|
| 250 |
return trim( preg_replace( '/\s+/', ' ', $gallery_html ) ); // remove any new lines from the output so that the reader parses it better |
| 251 |
} |
| 252 |
|
| 253 |
return ''; |
| 254 |
} |
| 255 |
|
| 256 |
/** |
| 257 |
* See if gallery is already defined. |
| 258 |
* |
| 259 |
* @return bool |
| 260 |
*/ |
| 261 |
public static function gallery_already_redefined() { |
| 262 |
global $shortcode_tags; |
| 263 |
$redefined = false; |
| 264 |
if ( ! isset( $shortcode_tags['gallery'] ) || $shortcode_tags['gallery'] !== 'gallery_shortcode' ) { |
| 265 |
$redefined = true; |
| 266 |
} |
| 267 |
/** |
| 268 |
* Filter the output of the check for another plugin or theme affecting WordPress galleries. |
| 269 |
* |
| 270 |
* This will let folks that replace core’s shortcode confirm feature parity with it, so Jetpack's Tiled Galleries can still work. |
| 271 |
* |
| 272 |
* @module tiled-gallery |
| 273 |
* |
| 274 |
* @since 3.1.0 |
| 275 |
* |
| 276 |
* @param bool $redefined Does another plugin or theme already redefines the default WordPress gallery? |
| 277 |
*/ |
| 278 |
return apply_filters( 'jetpack_tiled_gallery_shortcode_redefined', $redefined ); |
| 279 |
} |
| 280 |
|
| 281 |
/** |
| 282 |
* Initialize the tiled gallery. |
| 283 |
*/ |
| 284 |
public static function init() { |
| 285 |
if ( self::gallery_already_redefined() ) { |
| 286 |
return; |
| 287 |
} |
| 288 |
|
| 289 |
$gallery = new Jetpack_Tiled_Gallery(); |
| 290 |
add_filter( 'post_gallery', array( $gallery, 'gallery_shortcode' ), 1001, 2 ); |
| 291 |
} |
| 292 |
|
| 293 |
/** |
| 294 |
* Get the width of the gallery. |
| 295 |
* |
| 296 |
* @return int |
| 297 |
*/ |
| 298 |
public static function get_content_width() { |
| 299 |
$tiled_gallery_content_width = Jetpack::get_content_width(); |
| 300 |
|
| 301 |
if ( ! $tiled_gallery_content_width ) { |
| 302 |
$tiled_gallery_content_width = 500; |
| 303 |
} |
| 304 |
|
| 305 |
/** |
| 306 |
* Filter overwriting the default content width. |
| 307 |
* |
| 308 |
* @module tiled-gallery |
| 309 |
* |
| 310 |
* @since 2.1.0 |
| 311 |
* |
| 312 |
* @param string $tiled_gallery_content_width Default Tiled Gallery content width. |
| 313 |
*/ |
| 314 |
return apply_filters( 'tiled_gallery_content_width', $tiled_gallery_content_width ); |
| 315 |
} |
| 316 |
|
| 317 |
/** |
| 318 |
* Media UI integration |
| 319 |
* |
| 320 |
* @param array $types - the type of gallery. |
| 321 |
* |
| 322 |
* @return array |
| 323 |
*/ |
| 324 |
public function jetpack_gallery_types( $types ) { |
| 325 |
if ( get_option( 'tiled_galleries' ) && isset( $types['default'] ) ) { |
| 326 |
// Tiled is set as the default, meaning that type='default' |
| 327 |
// will still display the mosaic. |
| 328 |
$types['thumbnails'] = $types['default']; |
| 329 |
unset( $types['default'] ); |
| 330 |
} |
| 331 |
|
| 332 |
$types['rectangular'] = __( 'Tiled Mosaic', 'jetpack' ); |
| 333 |
$types['square'] = __( 'Square Tiles', 'jetpack' ); |
| 334 |
$types['circle'] = __( 'Circles', 'jetpack' ); |
| 335 |
$types['columns'] = __( 'Tiled Columns', 'jetpack' ); |
| 336 |
|
| 337 |
return $types; |
| 338 |
} |
| 339 |
|
| 340 |
/** |
| 341 |
* Get the default gallery type. |
| 342 |
* |
| 343 |
* @return string |
| 344 |
*/ |
| 345 |
public function jetpack_default_gallery_type() { |
| 346 |
return ( get_option( 'tiled_galleries' ) ? 'rectangular' : 'default' ); |
| 347 |
} |
| 348 |
|
| 349 |
/** |
| 350 |
* Get the talaveras. |
| 351 |
* |
| 352 |
* @return array |
| 353 |
*/ |
| 354 |
public static function get_talaveras() { |
| 355 |
return self::$talaveras; |
| 356 |
} |
| 357 |
|
| 358 |
/** |
| 359 |
* Add a checkbox field to the Carousel section in Settings > Media |
| 360 |
* for setting tiled galleries as the default. |
| 361 |
*/ |
| 362 |
public function settings_api_init() { |
| 363 |
global $wp_settings_sections; |
| 364 |
|
| 365 |
// Add the setting field [tiled_galleries] and place it in Settings > Media |
| 366 |
if ( isset( $wp_settings_sections['media']['carousel_section'] ) ) { |
| 367 |
$section = 'carousel_section'; |
| 368 |
} else { |
| 369 |
$section = 'default'; |
| 370 |
} |
| 371 |
|
| 372 |
add_settings_field( 'tiled_galleries', __( 'Tiled Galleries', 'jetpack' ), array( $this, 'setting_html' ), 'media', $section ); |
| 373 |
register_setting( 'media', 'tiled_galleries', 'esc_attr' ); |
| 374 |
} |
| 375 |
|
| 376 |
/** |
| 377 |
* Render the settings HTML. |
| 378 |
*/ |
| 379 |
public function setting_html() { |
| 380 |
echo '<label><input name="tiled_galleries" type="checkbox" value="1" ' . |
| 381 |
checked( 1, '' !== get_option( 'tiled_galleries' ), false ) . ' /> ' . |
| 382 |
esc_html__( 'Display all your gallery pictures in a cool mosaic.', 'jetpack' ) . '</br></label>'; |
| 383 |
} |
| 384 |
} |
| 385 |
|
| 386 |
add_action( 'init', array( 'Jetpack_Tiled_Gallery', 'init' ) ); |
| 387 |
|