PluginProbe ʕ •ᴥ•ʔ
Responsive Lightbox & Gallery / 2.7.2
Responsive Lightbox & Gallery v2.7.2
2.7.8 trunk 1.0.0 1.0.1 1.0.1.1 1.0.2 1.0.3 1.0.4 1.1.0 1.1.1 1.1.2 1.2.0 1.2.1 1.2.2 1.2.3 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.4.0 1.4.0.1 1.4.1 1.4.11 1.4.12 1.4.13 1.4.14 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.6.0 1.6.1 1.6.10 1.6.11 1.6.12 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 2.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.1 2.2.0 2.2.1 2.2.2 2.2.3 2.2.3.1 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.3.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.4.8 2.4.9 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.6.0 2.6.1 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7
responsive-lightbox / includes / class-galleries.php
responsive-lightbox / includes Last commit date
galleries 4 months ago providers 4 months ago settings 4 months ago class-fast-image.php 2 years ago class-folders.php 4 months ago class-frontend.php 4 months ago class-galleries.php 4 months ago class-multilang.php 2 years ago class-remote-library-api.php 4 months ago class-remote-library.php 4 months ago class-settings-api.php 4 months ago class-settings-data.php 4 months ago class-settings-pages.php 4 months ago class-settings.php 4 months ago class-tour.php 4 months ago class-welcome.php 2 years ago class-widgets.php 2 years ago functions.php 3 years ago
class-galleries.php
1856 lines
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 // Include gallery traits
7 require_once( RESPONSIVE_LIGHTBOX_PATH . 'includes/galleries/trait-gallery-duplicate.php' );
8 require_once( RESPONSIVE_LIGHTBOX_PATH . 'includes/galleries/trait-gallery-preview.php' );
9 require_once( RESPONSIVE_LIGHTBOX_PATH . 'includes/galleries/trait-gallery-sanitize.php' );
10 require_once( RESPONSIVE_LIGHTBOX_PATH . 'includes/galleries/trait-gallery-ajax.php' );
11 require_once( RESPONSIVE_LIGHTBOX_PATH . 'includes/galleries/trait-gallery-image-methods.php' );
12
13 /**
14 * Responsive Lightbox Galleries class.
15 *
16 * @class Responsive_Lightbox_Galleries
17 */
18 class Responsive_Lightbox_Galleries {
19
20 use Responsive_Lightbox_Gallery_Duplicate;
21 use Responsive_Lightbox_Gallery_Preview;
22 use Responsive_Lightbox_Gallery_Sanitize;
23 use Responsive_Lightbox_Gallery_Ajax;
24 use Responsive_Lightbox_Galleries_Image_Methods;
25
26 public $fields;
27 private $tabs;
28 private $sizes;
29 private $gallery_args;
30 private $menu_item;
31 private $revision_id;
32 private $allowed_select_html = [
33 'select' => [
34 'name' => true,
35 'id' => true,
36 'class' => true,
37 'required' => true,
38 'tabindex' => true,
39 'aria-describedby' => true
40 ],
41 'option' => [
42 'value' => true,
43 'class' => true,
44 'selected' => true
45 ]
46 ];
47
48
49 /**
50 * Class constructor.
51 *
52 * @param bool $read_only Whether is it read only mode
53 * @return void
54 */
55 public function __construct( $read_only = false ) {
56 // set instance
57 Responsive_Lightbox()->galleries = $this;
58
59 if ( $read_only )
60 return;
61
62 // Initialize gallery settings API - all tabs managed by adapter
63 include_once( RESPONSIVE_LIGHTBOX_PATH . 'includes/galleries/class-gallery-api.php' );
64 Responsive_Lightbox()->gallery_api = new Responsive_Lightbox_Gallery_API();
65
66 // actions
67 add_action( 'init', array( $this, 'init' ), 11 );
68 add_action( 'admin_init', array( $this, 'init_admin' ) );
69 add_action( 'current_screen', array( $this, 'clear_metaboxes' ) );
70 add_action( 'edit_form_after_title', array( $this, 'after_title_nav_menu' ) );
71 add_action( 'admin_footer', array( $this, 'modal_gallery_template' ) );
72 add_action( 'customize_controls_print_footer_scripts', array( $this, 'modal_gallery_template' ) );
73 add_action( 'media_buttons', array( $this, 'add_gallery_button' ) );
74 add_action( 'add_meta_boxes_rl_gallery', array( $this, 'add_meta_boxes' ) );
75 add_action( 'save_post_rl_gallery', array( $this, 'save_post' ), 10, 3 );
76 add_action( 'manage_rl_gallery_posts_custom_column', array( $this, 'gallery_columns_content' ), 10, 2 );
77 add_action( 'admin_action_duplicate_gallery', array( $this, 'duplicate_gallery' ) );
78 add_action( 'wp_ajax_rl-get-menu-content', array( $this, 'get_menu_content' ) );
79 add_action( 'wp_ajax_rl-get-preview-content', array( $this, 'get_gallery_preview_content' ) );
80 add_action( 'wp_ajax_rl-post-get-galleries', array( $this, 'post_get_galleries' ) );
81 add_action( 'wp_ajax_rl-post-gallery-preview', array( $this, 'post_gallery_preview' ) );
82 add_action( 'wp_ajax_rl-get-gallery-page-content', array( $this, 'get_gallery_page' ) );
83 add_action( 'wp_ajax_nopriv_rl-get-gallery-page-content', array( $this, 'get_gallery_page' ) );
84 add_action( '_wp_put_post_revision', array( $this, 'save_revision' ) );
85 add_action( 'delete_attachment', array( $this, 'delete_attachment' ) );
86 add_action( 'shutdown', array( $this, 'shutdown_preview' ) );
87 add_action( 'wp_loaded', array( $this, 'maybe_change_lightbox' ), 1 );
88
89 // filters
90 add_filter( 'manage_rl_gallery_posts_columns', array( $this, 'gallery_columns' ) );
91 add_filter( 'admin_post_thumbnail_html', array( $this, 'admin_post_thumbnail_html' ), 10, 3 );
92 add_filter( 'post_thumbnail_html', array( $this, 'post_thumbnail_html' ), 10, 5 );
93 add_filter( 'preview_post_link', array( $this, 'preview_post_link' ) );
94 add_filter( 'post_row_actions', array( $this, 'post_row_actions_duplicate' ), 10, 2 );
95
96 if ( ! empty( $_POST['rl_active_tab'] ) )
97 add_filter( 'redirect_post_location', array( $this, 'add_active_tab' ) );
98 }
99
100 /**
101 * Get class data.
102 *
103 * @param string $attr
104 * @return mixed
105 */
106 public function get_data( $attr ) {
107 return property_exists( $this, $attr ) ? $this->{$attr} : null;
108 }
109
110 /**
111 * Get default gallery single image template.
112 *
113 * @param array $args Template arguments
114 * @return string
115 */
116 public function get_media_item_template( $args = [] ) {
117 $args = array_merge(
118 array(
119 'draggable' => false,
120 'editable' => false,
121 'removable' => false,
122 'changeable' => false
123 ),
124 $args
125 );
126
127 return '
128 <li class="rl-gallery-image__MEDIA_STATUS__" data-attachment_id="__MEDIA_ID__" data-type="__MEDIA_TYPE__"' . ( $args['draggable'] ? ' style="cursor: move;"' : '' ) . '>
129 <div class="rl-gallery-inner">
130 <div class="centered">
131 __MEDIA_DATA__
132 </div>
133 </div>
134 <div class="rl-gallery-actions">' .
135 ( $args['changeable'] ? '<a href="#" class="rl-gallery-image-status dashicons dashicons-marker" title="' . esc_attr__( 'Status', 'responsive-lightbox' ) . '"></a>' : '' ) .
136 ( $args['editable'] ? '<a href="#" class="rl-gallery-image-edit dashicons dashicons-edit" title="' . esc_attr__( 'Edit image', 'responsive-lightbox' ) . '"></a>' : '' ) .
137 ( $args['removable'] ? '<a href="#" class="rl-gallery-image-remove dashicons dashicons-no" title="' . esc_attr__( 'Remove image', 'responsive-lightbox' ) . '"></a>' : '' ) . '
138 </div>
139 </li>';
140 }
141
142 /**
143 * Get default gallery embed template.
144 *
145 * @param bool $js
146 * @return string
147 */
148 public function get_media_embed_template( $js = false ) {
149 $html = '';
150
151 if ( $js )
152 $html .= '<div data-id="__EMBED_ID__" style="display: none;">';
153
154 $html .= '
155 <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][url]" data-type="url" value="__EMBED_URL__">
156 <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][width]" data-type="width" value="__EMBED_WIDTH__">
157 <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][height]" data-type="height" value="__EMBED_HEIGHT__">
158 <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][thumbnail_url]" data-type="thumbnail_url" value="__EMBED_THUMBNAIL_URL__">
159 <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][thumbnail_width]" data-type="thumbnail_width" value="__EMBED_THUMBNAIL_WIDTH__">
160 <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][thumbnail_height]" data-type="thumbnail_height" value="__EMBED_THUMBNAIL_HEIGHT__">
161 <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][title]" data-type="title" value="__EMBED_TITLE__">
162 <textarea class="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][caption]" data-type="caption">__EMBED_DESCRIPTION__</textarea>
163 <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][date]" data-type="date" value="__EMBED_DATE__">';
164
165 if ( $js )
166 $html .= '</div>';
167
168 return $html;
169 }
170
171 /**
172 * Set the current menu item for image source resolution.
173 *
174 * Used by gallery adapter to set menu_item before calling get_gallery_images().
175 *
176 * @param string $menu_item Menu item key.
177 * @return void
178 */
179 public function set_menu_item( $menu_item ) {
180 $this->menu_item = sanitize_key( $menu_item );
181 }
182
183 /**
184 * Get default gallery exclude input template.
185 *
186 * @param string $tab_id
187 * @param string $menu_item
188 * @param string $field_name
189 * @param mixed $excluded_value
190 * @return string
191 */
192 public function get_media_exclude_input_template( $tab_id = '', $menu_item = '', $field_name = '', $excluded_value = '' ) {
193 $template = '<input type="hidden" class="rl-gallery-exclude" name="rl_gallery[__MEDIA_TAB_ID__][__MEDIA_MENU_ITEM__][__MEDIA_FIELD_NAME__][exclude][]" value="__MEDIA_FIELD_VALUE__" />';
194
195 if ( $tab_id === '' && $menu_item === '' && $field_name === '' && $excluded_value === '' )
196 return str_replace( '__MEDIA_FIELD_VALUE__', '', $template );
197
198 return str_replace(
199 [
200 '__MEDIA_TAB_ID__',
201 '__MEDIA_MENU_ITEM__',
202 '__MEDIA_FIELD_NAME__',
203 '__MEDIA_FIELD_VALUE__'
204 ],
205 [
206 esc_attr( $tab_id ),
207 esc_attr( $menu_item ),
208 esc_attr( $field_name ),
209 empty( $excluded_value ) ? '' : esc_attr( $excluded_value )
210 ],
211 $template
212 );
213 }
214
215 /**
216 * Load needed data.
217 *
218 * @return void
219 */
220 public function init() {
221 // register shortcode
222 add_shortcode( 'rl_gallery', array( $this, 'gallery_shortcode' ) );
223
224 // get main instance
225 $rl = Responsive_Lightbox();
226
227 // set lightbox script for infinite scroll pages
228 if ( isset( $_GET['rl_gallery_no'], $_GET['rl_page'], $_GET['rl_lightbox_script'] ) )
229 $rl->set_lightbox_script( sanitize_key( $_GET['rl_lightbox_script'] ) );
230
231 $config_menu_items = apply_filters( 'rl_gallery_types', $rl->get_data( 'gallery_types' ) );
232 $config_menu_items['default'] = __( 'Global', 'responsive-lightbox' );
233
234 // set tabs
235 $this->tabs = apply_filters(
236 'rl_gallery_tabs',
237 array(
238 'images' => array(
239 'label' => __( 'Images', 'responsive-lightbox' ),
240 'description' => __( 'The settings below adjust the contents of the gallery.', 'responsive-lightbox' ),
241 'menu_items' => array(
242 'media' => __( 'Media Library', 'responsive-lightbox' ),
243 'featured' => __( 'Featured Content', 'responsive-lightbox' )
244 )
245 ),
246 'config' => array(
247 'label' => __( 'Config', 'responsive-lightbox' ),
248 'description' => __( 'The settings below allow you to select a gallery type and adjust the gallery options.', 'responsive-lightbox' ),
249 'menu_items' => $config_menu_items
250 ),
251 'design' => array(
252 'label' => __( 'Design', 'responsive-lightbox' ),
253 'description' => __( 'The settings below adjust the gallery design options.', 'responsive-lightbox' )
254 ),
255 'paging' => array(
256 'label' => __( 'Paging', 'responsive-lightbox' ),
257 'description' => __( 'The settings below adjust the gallery pagination options.', 'responsive-lightbox' )
258 ),
259 'lightbox' => array(
260 'label' => __( 'Lightbox', 'responsive-lightbox' ),
261 'description' => __( 'The settings below adjust the lightbox options.', 'responsive-lightbox' ),
262 ),
263 'misc' => array(
264 'label' => __( 'Misc', 'responsive-lightbox' ),
265 'description' => __( 'The settings below adjust miscellaneous options.', 'responsive-lightbox' ),
266 )
267 )
268 );
269
270 // add folders if active
271 if ( $rl->options['folders']['active'] )
272 $this->tabs['images']['menu_items']['folders'] = __( 'Media Folder', 'responsive-lightbox' );
273
274 // add remote library if active
275 $this->tabs['images']['menu_items']['remote_library'] = __( 'Remote Library', 'responsive-lightbox' );
276
277 // use sizes as keys and values
278 $this->sizes = $this->get_image_sizes();
279 $sizes = array_combine( array_keys( $this->sizes ), array_keys( $this->sizes ) );
280
281 // add default, custom and full image size
282 $sizes['full'] = __( 'Full size', 'responsive-lightbox' );
283 $sizes['global'] = __( 'Global', 'responsive-lightbox' );
284 $sizes['rl_custom_size'] = __( 'Custom size', 'responsive-lightbox' );
285
286 // positions
287 $positions = array(
288 'none' => __( 'None', 'responsive-lightbox' ),
289 'top' => __( 'Top', 'responsive-lightbox' ),
290 'bottom' => __( 'Bottom', 'responsive-lightbox' )
291 );
292
293 // merge titles
294 $merged_titles = array( 'global' => __( 'Global', 'responsive-lightbox' ) ) + $rl->settings->get_data( 'image_titles' );
295
296 // set fields
297 $this->fields = array(
298 'images' => [],
299 // Field definitions for config, design, paging, lightbox, misc are populated from adapter classes below.
300 // This ensures single source of truth and eliminates duplication while maintaining get_data('fields') contract.
301 'config' => [],
302 'design' => [],
303 'paging' => [],
304 'lightbox' => [],
305 'misc' => []
306 );
307
308 // Populate adapter-owned tabs from their classes (single source of truth - v2.7.1+)
309 // This eliminates field duplication while maintaining get_data('fields') public contract
310 // for core frontend and gallery add-ons that access design/lightbox/misc fields.
311 if ( isset( $rl->gallery_api ) ) {
312 foreach ( [ 'images', 'config', 'design', 'paging', 'lightbox', 'misc' ] as $adapter_tab ) {
313 if ( $rl->gallery_api->is_managed_tab( $adapter_tab ) ) {
314 $tab_data = $rl->gallery_api->get_tab_definition( $adapter_tab );
315 if ( ! empty( $tab_data ) ) {
316 $this->fields[$adapter_tab] = $tab_data;
317 }
318 }
319 }
320 }
321 }
322
323 /**
324 * Add a gallery shortcode.
325 *
326 * @param array $args Shortcode arguments
327 * @return string
328 */
329 public function gallery_shortcode( $args ) {
330 // enable only for frontend previews
331 if ( ! is_admin() && is_preview() )
332 add_filter( 'get_post_metadata', array( $this, 'filter_preview_metadata' ), 10, 4 );
333
334 // prepare defaults
335 $defaults = [ 'id' => 0 ];
336
337 // merge defaults with arguments
338 $args = array_merge( $defaults, $args );
339
340 // parse id
341 $args['id'] = (int) $args['id'];
342
343 // is it gallery?
344 if ( get_post_type( $args['id'] ) !== 'rl_gallery' )
345 return '';
346
347 // private gallery?
348 if ( get_post_status( $args['id'] ) === 'private' && ! current_user_can( 'read_private_posts' ) )
349 return '';
350
351 $images_args = [ 'exclude' => true ];
352
353 if ( isset( $args['preview'] ) )
354 $images_args['preview'] = (bool) $args['preview'];
355 elseif( isset( $_GET['rl_gallery_revision_id'], $_GET['preview'] ) && $_GET['preview'] === 'true' )
356 $images_args['preview'] = true;
357 else
358 $images_args['preview'] = false;
359
360 // get images
361 $images = $this->get_gallery_images( $args['id'], $images_args );
362
363 if ( ! $images )
364 return '';
365
366 $attachments = [];
367
368 // build config
369 foreach ( $images as $image ) {
370 if ( ! empty( $image['id'] ) )
371 $attachments[] = $image['id'];
372 }
373
374 // get config data
375 $config = get_post_meta( $args['id'], '_rl_config', true );
376 if ( ! is_array( $config ) )
377 $config = [];
378
379 // get main instance
380 $rl = Responsive_Lightbox();
381
382 // available gallery types
383 $gallery_types = apply_filters( 'rl_gallery_types', $rl->get_data( 'gallery_types' ) );
384 if ( ! is_array( $gallery_types ) )
385 $gallery_types = [];
386
387 // prepare gallery shortcode parameters
388 $fields = [];
389 $gallery_type = '';
390 $menu_item = ! empty( $config['menu_item'] ) ? $config['menu_item'] : 'default';
391 if ( ! empty( $menu_item ) && $menu_item !== 'default' && ! array_key_exists( $menu_item, $gallery_types ) )
392 $menu_item = 'default';
393
394 // valid menu item?
395 if ( ! empty( $menu_item ) ) {
396 // assign data from db
397 $data = isset( $config[$menu_item] ) && is_array( $config[$menu_item] ) ? $config[$menu_item] : [];
398
399 foreach ( $rl->frontend->get_default_gallery_fields() as $field_name => $field_args ) {
400 // replace default values
401 if ( array_key_exists( $field_name, $data ) )
402 $fields[$field_name] = $data[$field_name];
403 }
404
405 // is it default gallery type?
406 if ( $menu_item === 'default' ) {
407 // set new gallery type
408 $gallery_type = $rl->options['settings']['builder_gallery'];
409
410 // fallback to a valid gallery type
411 if ( empty( $gallery_type ) || ! array_key_exists( $gallery_type, $gallery_types ) )
412 $gallery_type = $rl->defaults['settings']['builder_gallery'];
413
414 // assign gallery settings
415 $gallery_fields = $rl->settings->get_setting_fields( $gallery_type . '_gallery' );
416 // assign gallery defaults
417 if ( array_key_exists( $gallery_type . '_gallery', $rl->options ) )
418 $gallery_defaults = $rl->options[$gallery_type . '_gallery'];
419 } else {
420 $gallery_type = $menu_item;
421
422 // fallback to a valid gallery type
423 if ( empty( $gallery_type ) || ! array_key_exists( $gallery_type, $gallery_types ) )
424 $gallery_type = $rl->options['settings']['builder_gallery'];
425
426 // assign gallery settings
427 $gallery_fields = $rl->settings->get_setting_fields( $menu_item . '_gallery' );
428 // assign gallery defaults
429 if ( array_key_exists( $menu_item . '_gallery', $rl->defaults ) )
430 $gallery_defaults = $rl->defaults[$menu_item . '_gallery'];
431 }
432
433 if ( ! isset( $gallery_defaults ) && ! empty( $gallery_type ) && array_key_exists( $gallery_type . '_gallery', $rl->defaults ) )
434 $gallery_defaults = $rl->defaults[$gallery_type . '_gallery'];
435
436 if ( ! isset( $gallery_fields ) && ! empty( $gallery_type ) )
437 $gallery_fields = $rl->settings->get_setting_fields( $gallery_type . '_gallery' );
438
439 if ( isset( $gallery_fields, $gallery_defaults ) ) {
440 // run through all fields
441 foreach ( $gallery_fields as $field_name => $field_args ) {
442 if ( $field_args['type'] === 'multiple' ) {
443 foreach ( $field_args['fields'] as $subfield_name => $subfield_args ) {
444 // field exists in db?
445 if ( array_key_exists( $subfield_name, $data ) )
446 $fields[$subfield_name] = $data[$subfield_name];
447 elseif ( isset( $rl->options[$gallery_type . '_gallery'][ $subfield_name ] ) )
448 $fields[$subfield_name] = $rl->options[$gallery_type . '_gallery'][ $subfield_name ];
449 else
450 $fields[$subfield_name] = $gallery_defaults[$subfield_name];
451 }
452 } else {
453 // field exists in db?
454 if ( array_key_exists( $field_name, $data ) )
455 $fields[$field_name] = $data[$field_name];
456 elseif ( isset( $rl->options[$gallery_type . '_gallery'][ $field_name ] ) )
457 $fields[$field_name] = $rl->options[$gallery_type . '_gallery'][ $field_name ];
458 else
459 $fields[$field_name] = $gallery_defaults[$field_name];
460 }
461 }
462 }
463 // add gallery type
464 if ( ! empty( $gallery_type ) && array_key_exists( $gallery_type, $gallery_types ) )
465 $fields['type'] = $gallery_type;
466 }
467
468 // ensure gallery type is present and valid
469 if ( empty( $fields['type'] ) || ! array_key_exists( $fields['type'], $gallery_types ) ) {
470 $fallback_type = $rl->options['settings']['builder_gallery'];
471 if ( empty( $fallback_type ) || ! array_key_exists( $fallback_type, $gallery_types ) )
472 $fallback_type = $rl->defaults['settings']['builder_gallery'];
473
474 if ( ! empty( $fallback_type ) && array_key_exists( $fallback_type, $gallery_types ) )
475 $fields['type'] = $fallback_type;
476 }
477
478 $shortcode = '';
479
480 foreach ( $fields as $arg => $value ) {
481 if ( is_array( $value ) )
482 $shortcode .= ' ' . esc_attr( $arg ) . '="' . esc_attr( (string) implode( ',', $value ) ) . '"';
483 else
484 $shortcode .= ' ' . esc_attr( $arg ) . '="' . esc_attr( (string) $value ) . '"';
485 }
486
487 // get design data
488 $design = get_post_meta( $args['id'], '_rl_design', true );
489
490 if ( ! empty( $design['menu_item'] ) ) {
491 $design_data = $design[$design['menu_item']];
492
493 // remove show_title to avoid shortcode attribute duplication
494 if ( isset( $design_data['show_title'] ) ) {
495 if ( ! isset( $design_data['design_show_title'] ) )
496 $design_data['design_show_title'] = $design_data['show_title'];
497
498 unset( $design_data['show_title'] );
499 }
500
501 // remove show_caption to avoid shortcode attribute duplication
502 if ( isset( $design_data['show_caption'] ) ) {
503 if ( ! isset( $design_data['design_show_caption'] ) )
504 $design_data['design_show_caption'] = $design_data['show_caption'];
505
506 unset( $design_data['show_caption'] );
507 }
508
509 foreach ( $design_data as $arg => $value ) {
510 $shortcode .= ' ' . esc_attr( $arg ) . '="' . esc_attr( (string) $value ) . '"';
511 }
512 }
513
514 // get lightbox data
515 $lightbox = get_post_meta( $args['id'], '_rl_lightbox', true );
516
517 if ( ! empty( $lightbox['menu_item'] ) ) {
518 foreach ( $lightbox[$lightbox['menu_item']] as $arg => $value ) {
519 $shortcode .= ' ' . esc_attr( $arg ) . '="' . esc_attr( (string) $value ) . '"';
520 }
521 }
522
523 $forced_gallery_no = 0;
524
525 // check forced gallery number
526 if ( isset( $args['gallery_no'] ) ) {
527 $args['gallery_no'] = (int) $args['gallery_no'];
528
529 if ( $args['gallery_no'] > 0 )
530 $forced_gallery_no = $args['gallery_no'];
531 }
532
533 // get content
534 $content = do_shortcode( '[gallery rl_gallery_id="' . esc_attr( $args['id'] ) .'"' . ( $forced_gallery_no > 0 ? ' rl_gallery_no="' . (int) $forced_gallery_no .'"' : '' ) . ' include="' . ( empty( $attachments ) ? '' : esc_attr( implode( ',', $attachments ) ) ) . '"' . $shortcode . ']' );
535
536 // make sure every filter is available in frontend ajax
537 if ( wp_doing_ajax() )
538 $content = $rl->frontend->add_lightbox( $content );
539
540 return $content;
541 }
542
543 /**
544 * Add a gallery button.
545 *
546 * @param string $editor_id Editor ID
547 * @return void
548 */
549 public function add_gallery_button( $editor_id ) {
550 if ( get_post_type() === 'rl_gallery' )
551 return;
552
553 $this->enqueue_gallery_scripts_styles();
554
555 echo '<button type="button" id="rl-insert-modal-gallery-button" class="button" data-editor="' . esc_attr( $editor_id ) . '"><span class="wp-media-buttons-icon dashicons dashicons-format-gallery"></span> ' . esc_html__( 'Add Gallery', 'responsive-lightbox' ) . '</button>';
556 }
557
558 /**
559 * Enqueue scripts and styles needed for gallery modal.
560 *
561 * @global string $pagenow
562 *
563 * @return void
564 */
565 public function enqueue_gallery_scripts_styles() {
566 global $pagenow;
567
568 // count how many times function was executed
569 static $run = 0;
570
571 // allow this only once
572 if ( $run > 0 )
573 return;
574
575 $run++;
576
577 // get main instance
578 $rl = Responsive_Lightbox();
579
580 wp_enqueue_script( 'responsive-lightbox-admin-gallery', RESPONSIVE_LIGHTBOX_URL . '/js/admin-gallery.js', array( 'jquery', 'underscore' ), $rl->defaults['version'], false );
581
582 // prepare script data
583 $script_data = [
584 'nonce' => wp_create_nonce( 'rl-gallery-post' ),
585 'post_id' => get_the_ID(),
586 'page' => esc_url( $pagenow )
587 ];
588
589 wp_add_inline_script( 'responsive-lightbox-admin-gallery', 'var rlArgsGallery = ' . wp_json_encode( $script_data ) . ";\n", 'before' );
590
591 wp_enqueue_style( 'responsive-lightbox-admin-gallery', RESPONSIVE_LIGHTBOX_URL . '/css/admin-gallery.css', [], $rl->defaults['version'] );
592 }
593
594 /**
595 * Modal gallery HTML template.
596 *
597 * @global string $wp_version
598 * @global string $pagenow
599 *
600 * @return void
601 */
602 public function modal_gallery_template() {
603 global $wp_version;
604 global $pagenow;
605
606 // display only for post edit pages
607 if ( ! ( ( ( $pagenow === 'post.php' || $pagenow === 'post-new.php' ) && get_post_type() !== 'rl_gallery' ) || ( version_compare( $wp_version, '5.8', '>=' ) && ( $pagenow === 'widgets.php' || $pagenow === 'customize.php' ) ) ) )
608 return;
609
610 // get main instance
611 $rl = Responsive_Lightbox();
612
613 $categories = '';
614
615 // builder categories?
616 if ( $rl->options['builder']['categories'] ) {
617 $terms = get_terms(
618 array(
619 'taxonomy' => 'rl_category',
620 'orderby' => 'name',
621 'order' => 'ASC',
622 'hide_empty' => false,
623 'fields' => 'id=>name'
624 )
625 );
626
627 // get categories dropdown
628 $categories = wp_dropdown_categories(
629 array(
630 'orderby' => 'name',
631 'order' => 'asc',
632 'show_option_none' => empty( $terms ) ? __( 'All categories', 'responsive-lightbox' ) : '',
633 'show_option_all' => __( 'All categories', 'responsive-lightbox' ),
634 'show_count' => false,
635 'hide_empty' => false,
636 'option_none_value' => 0,
637 'hierarchical' => true,
638 'selected' => 0,
639 'taxonomy' => 'rl_category',
640 'hide_if_empty' => false,
641 'echo' => false,
642 'id' => 'rl-media-attachment-categories',
643 'class' => 'attachment-filters',
644 'name' => ''
645 )
646 );
647 }
648
649 echo '
650 <div id="rl-modal-gallery" style="display: none;">
651 <div class="media-modal wp-core-ui">
652 <button type="button" class="media-modal-close"><span class="media-modal-icon"><span class="screen-reader-text">' . esc_html__( 'Close', 'responsive-lightbox' ) . '</span></span></button>
653 <div class="media-modal-content">
654 <div class="media-frame mode-select wp-core-ui hide-menu hide-router">
655 <div class="media-frame-title">
656 <h1 class="wrap">' . esc_html__( 'Insert Gallery', 'responsive-lightbox' ) . ' <a class="rl-reload-galleries page-title-action" href="#">' . esc_html__( 'Reload', 'responsive-lightbox' ). '</a><span class="rl-gallery-reload-spinner spinner"></span></h1>
657 </div>
658 <div class="media-frame-content" data-columns="0">
659 <div class="attachments-browser">
660 <div class="uploader-inline rl-no-galleries" style="display: none;">
661 <div class="uploader-inline-content has-upload-message">
662 <h2 class="upload-message">' . esc_html__( 'No items found.', 'responsive-lightbox' ) . '</h2>
663 <div class="upload-ui">
664 <h2 class="upload-instructions">' . esc_html__( 'No galleries? Create them first or try another search phrase.', 'responsive-lightbox' ) . '</h2>
665 </div>
666 </div>
667 </div>
668 <div class="media-toolbar">' . ( $rl->options['builder']['categories'] ? '
669 <div class="media-toolbar-secondary"><label for="rl-media-attachment-categories" class="screen-reader-text">' . esc_html__( 'Filter by category', 'responsive-lightbox' ) . '</label>' . ( $categories !== '' ? wp_kses( $categories, $this->allowed_select_html ) : '' ) . '</div>' : '' ) . '
670 <div class="media-toolbar-primary search-form">
671 <label for="rl-media-search-input" class="screen-reader-text">' . esc_html__( 'Search galleries', 'responsive-lightbox' ) . '</label><input type="search" placeholder="' . esc_attr__( 'Search galleries', 'responsive-lightbox' ) . '" id="rl-media-search-input" class="search">
672 </div>
673 </div>
674 <ul class="attachments rl-galleries-list ui-sortable ui-sortable-disabled">
675 </ul>
676 <div class="media-sidebar visible">
677 <h2>' . esc_html__( 'Select A Gallery', 'responsive-lightbox' ) . '</h2>
678 <p>' . esc_html__( 'To select a gallery simply click on one of the boxes to the left.', 'responsive-lightbox' ) . '</p>
679 <p>' . esc_html__( 'To insert your gallery into the editor, click on the "Insert Gallery" button below.', 'responsive-lightbox' ) . '</p>
680 </div>
681 </div>
682 </div>
683 <div class="media-frame-toolbar">
684 <div class="media-toolbar">
685 <div class="media-toolbar-secondary">
686 <div class="media-selection empty">
687 <div class="selection-info">
688 <span class="rl-gallery-count count">' . esc_html( sprintf( _n( '%s image', '%s images', 0, 'responsive-lightbox' ), 0 ) ) . '</span>
689 <a href="" class="button-link rl-edit-gallery-link">' . esc_html__( 'Edit gallery', 'responsive-lightbox' ) . '</a>
690 </div>
691 <div class="selection-view">
692 <span class="rl-gallery-images-spinner spinner" style="display: none;"></span>
693 <ul class="attachments rl-attachments-list">
694 </ul>
695 </div>
696 </div>
697 </div>
698 <div class="media-toolbar-primary search-form">
699 <button style="display: none;" type="button" class="button media-button button-primary button-large rl-media-button-insert-gallery" disabled="disabled">' . esc_html__( 'Insert gallery into post', 'responsive-lightbox') . '</button>
700 <button style="display: none;" type="button" class="button media-button button-primary button-large rl-media-button-select-gallery" disabled="disabled">' . esc_html__( 'Select gallery', 'responsive-lightbox') . '</button>
701 <button type="button" class="button media-button button-secondary button-large rl-media-button-cancel-gallery">' . esc_html__( 'Cancel', 'responsive-lightbox') . '</button>
702 </div>
703 </div>
704 </div>
705 </div>
706 </div>
707 </div>
708 <div class="media-modal-backdrop"></div>
709 </div>';
710 }
711
712 /**
713 * Add menu tabs after the post title.
714 *
715 * @global array $wp_meta_boxes
716 *
717 * @param object $post Post object
718 * @return void
719 */
720 public function after_title_nav_menu( $post ) {
721 if ( $post->post_type !== 'rl_gallery' )
722 return;
723
724 global $wp_meta_boxes;
725
726 // check active tab
727 $active_tab = isset( $_GET['rl_active_tab'] ) ? sanitize_key( $_GET['rl_active_tab'] ) : '';
728 $active_tab = ! empty( $active_tab ) && array_key_exists( $active_tab, $this->tabs ) ? $active_tab : 'images';
729
730 echo '
731 <div class="rl-settings-wrapper">
732 <h2 class="nav-tab-wrapper">';
733
734 foreach ( $this->tabs as $key => $data ) {
735 echo '
736 <a id="rl-gallery-tab-' . esc_attr( $key ) . '" class="rl-gallery-tab nav-tab' . ( $key === $active_tab ? ' nav-tab-active' : '' ) . '" href="#' . esc_attr( $key ) . '">' . esc_html( $data['label'] ) . '</a>';
737 }
738
739 echo '
740 </h2>';
741
742 do_meta_boxes( $post->post_type, 'responsive_lightbox_metaboxes', $post );
743
744 echo '
745 </div>';
746
747 unset( $wp_meta_boxes[$post->post_type]['responsive_lightbox_metaboxes'] );
748 }
749
750 /**
751 * Add class to hide metabox.
752 *
753 * @param array $classes
754 * @return array
755 */
756 public function hide_metabox( $classes ) {
757 $classes[] = 'rl-metabox-content';
758 $classes[] = 'rl-hide-metabox';
759
760 return $classes;
761 }
762
763 /**
764 * Add class to display the metabox.
765 *
766 * @param array $classes
767 * @return array
768 */
769 function display_metabox( $classes ) {
770 $classes[] = 'rl-metabox-content';
771 $classes[] = 'rl-display-metabox';
772
773 return $classes;
774 }
775
776 /**
777 * Add settings wrapper class to the metabox.
778 *
779 * @param array $classes
780 * @return array
781 */
782 public function add_settings_wrapper_class( $classes ) {
783 if ( ! in_array( 'rl-settings', $classes, true ) )
784 $classes[] = 'rl-settings';
785
786 return $classes;
787 }
788
789 /**
790 * Add active tab to post redirect destination URL.
791 *
792 * @param string $location Destination URL
793 * @return string
794 */
795 function add_active_tab( $location ) {
796 // check active tab
797 $active_tab = isset( $_POST['rl_active_tab'] ) ? sanitize_key( $_POST['rl_active_tab'] ) : '';
798
799 return add_query_arg( 'rl_active_tab', ! empty( $active_tab ) && array_key_exists( $active_tab, $this->tabs ) ? $active_tab : 'images', $location );
800 }
801
802 /**
803 * Add metaboxes.
804 *
805 * @return void
806 */
807 public function add_meta_boxes() {
808 // side metaboxes
809 add_meta_box( 'responsive-gallery-shortcode', esc_html__( 'Gallery Code', 'responsive-lightbox' ), array( $this, 'shortcode_metabox' ), 'rl_gallery', 'side', 'core' );
810 }
811
812 /**
813 * Get number of gallery images.
814 *
815 * @param int $gallery_id
816 * @return int
817 */
818 public function get_gallery_images_number( $gallery_id ) {
819 return count( $this->get_gallery_images( $gallery_id, [ 'count_images' => true, 'preview' => false, 'exclude' => true ] ) );
820 }
821
822 /**
823 * Sync gallery image counts when an attachment is deleted.
824 *
825 * @param int $attachment_id
826 * @return void
827 */
828 public function delete_attachment( $attachment_id ) {
829 $attachment_id = (int) $attachment_id;
830 if ( $attachment_id <= 0 )
831 return;
832
833 $galleries = get_posts( [
834 'post_type' => 'rl_gallery',
835 'post_status' => [ 'publish', 'private', 'draft', 'pending', 'future' ],
836 'fields' => 'ids',
837 'nopaging' => true,
838 'meta_query' => [
839 [
840 'key' => '_rl_images',
841 'value' => (string) $attachment_id,
842 'compare' => 'LIKE'
843 ]
844 ]
845 ] );
846
847 if ( empty( $galleries ) )
848 return;
849
850 foreach ( $galleries as $gallery_id ) {
851 update_post_meta( $gallery_id, '_rl_images_count', $this->get_gallery_images_number( $gallery_id ) );
852 }
853 }
854
855 /**
856 * Load featured content query args.
857 *
858 * @global string $pagenow
859 *
860 * @return void
861 */
862 public function init_admin() {
863 global $pagenow;
864
865 // check values
866 $post = isset( $_GET['post'] ) ? (int) $_GET['post'] : 0;
867 $post_id = isset( $_POST['post_ID'] ) ? (int) $_POST['post_ID'] : 0;
868 $action = isset( $_POST['action'] ) ? sanitize_key( $_POST['action'] ) : '';
869 $post_type = isset( $_POST['post_type'] ) ? sanitize_key( $_POST['post_type'] ) : '';
870
871 // prepare query arguments if needed
872 if ( ( $pagenow === 'post.php' && ( ( $post && get_post_type( $post ) === 'rl_gallery' ) || ( $post_id && get_post_type( $post_id ) === 'rl_gallery' ) ) ) || ( in_array( $pagenow, array( 'edit.php', 'post-new.php'), true ) && $post_type === 'rl_gallery' ) || ( $pagenow === 'admin-ajax.php' && $action && in_array( $action, array( 'rl-get-preview-content', 'rl-post-gallery-preview', 'rl-get-menu-content' ), true ) ) )
873 $this->fields['images']['featured'] = $this->prepare_featured_fields( $this->fields['images']['featured'] );
874
875 // add default thumbnail image if needed
876 if ( Responsive_Lightbox()->options['builder']['gallery_builder'] && $pagenow === 'edit.php' && $post_type && $post_type === 'rl_gallery' )
877 $this->maybe_generate_thumbnail();
878 }
879
880 /**
881 * Generate post thumbnail replacement.
882 *
883 * @return int
884 */
885 public function maybe_generate_thumbnail() {
886 // get old attachment
887 $thumbnail_id = get_posts(
888 array(
889 'name' => 'responsive-lightbox-thumbnail',
890 'post_type' => 'attachment',
891 'post_status' => 'inherit',
892 'numberposts' => 1,
893 'fields' => 'ids'
894 )
895 );
896
897 // no attachment?
898 if ( empty( $thumbnail_id ) ) {
899 // get new attachment
900 $thumbnail_id = get_posts(
901 array(
902 'name' => 'responsive-lightbox-thumbnail',
903 'post_type' => 'attachment',
904 'post_status' => 'pending',
905 'numberposts' => 1,
906 'fields' => 'ids'
907 )
908 );
909
910 // no attachment?
911 if ( empty( $thumbnail_id ) ) {
912 // get upload directory data
913 $wp_upload_dir = wp_upload_dir();
914
915 // get file path
916 $filepath = str_replace( '\\', '/', RESPONSIVE_LIGHTBOX_PATH . 'images/responsive-lightbox-thumbnail.png' );
917
918 // get file name
919 $filename = basename( $filepath );
920
921 // new filepath in upload dir
922 $new_filepath = $wp_upload_dir['path'] . '/' . $filename;
923
924 // copty file to upload dir
925 copy( $filepath, $new_filepath );
926
927 // get type of file
928 $filetype = wp_check_filetype( $filename );
929
930 // force pending status for the attachment
931 add_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
932
933 // insert attachment
934 $thumbnail_id = wp_insert_attachment(
935 array(
936 'guid' => $wp_upload_dir['url'] . '/' . $filename,
937 'post_mime_type' => $filetype['type'],
938 'post_title' => preg_replace( '/\.[^.]+$/', '', $filename ),
939 'post_content' => '',
940 'post_parent' => 0,
941 'post_status' => 'inherit'
942 ),
943 $new_filepath,
944 0
945 );
946
947 remove_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
948
949 // success?
950 if ( $thumbnail_id ) {
951 // make sure that this file is included
952 require_once( ABSPATH . 'wp-admin/includes/image.php' );
953
954 // update database with generated metadata for the attachment
955 wp_update_attachment_metadata( $thumbnail_id, wp_generate_attachment_metadata( $thumbnail_id, $new_filepath ) );
956 }
957 } else
958 $thumbnail_id = $thumbnail_id[0];
959 } else {
960 // force pending status for the attachment
961 add_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
962
963 $thumbnail_id = wp_update_post(
964 array(
965 'ID' => $thumbnail_id[0],
966 'post_status' => 'pending'
967 )
968 );
969
970 remove_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
971 }
972
973 return (int) $thumbnail_id;
974 }
975
976 /**
977 * Get video thumbnail replacement.
978 *
979 * @param int $post_id
980 * @return int
981 */
982 public function get_video_thumbnail_id( $post_id ) {
983 $thumbnail_id = 0;
984
985 // try to get video thumbnail
986 $attachment_id = (int) get_post_thumbnail_id( $post_id );
987
988 // real attachment?
989 if ( wp_attachment_is_image( $attachment_id ) )
990 $thumbnail_id = $attachment_id;
991
992 // try to get default video poster image
993 if ( ! $thumbnail_id ) {
994 $thumbnail_id = get_posts(
995 array(
996 'name' => 'responsive-lightbox-video-thumbnail',
997 'post_type' => 'attachment',
998 'post_status' => 'inherit',
999 'numberposts' => 1,
1000 'fields' => 'ids'
1001 )
1002 );
1003 }
1004
1005 // no attachment?
1006 if ( ! $thumbnail_id ) {
1007 // get new attachment
1008 $thumbnail_id = get_posts(
1009 array(
1010 'name' => 'responsive-lightbox-video-thumbnail',
1011 'post_type' => 'attachment',
1012 'post_status' => 'pending',
1013 'numberposts' => 1,
1014 'fields' => 'ids'
1015 )
1016 );
1017
1018 // no attachment?
1019 if ( ! $thumbnail_id ) {
1020 // get upload directory data
1021 $wp_upload_dir = wp_upload_dir();
1022
1023 // get file path
1024 $filepath = str_replace( '\\', '/', RESPONSIVE_LIGHTBOX_PATH . 'images/responsive-lightbox-video-thumbnail.png' );
1025
1026 // get file name
1027 $filename = basename( $filepath );
1028
1029 // new filepath in upload dir
1030 $new_filepath = $wp_upload_dir['path'] . '/' . $filename;
1031
1032 // copty file to upload dir
1033 copy( $filepath, $new_filepath );
1034
1035 // get type of file
1036 $filetype = wp_check_filetype( $filename );
1037
1038 // force pending status for the attachment
1039 add_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
1040
1041 // insert attachment
1042 $thumbnail_id = wp_insert_attachment(
1043 array(
1044 'guid' => $wp_upload_dir['url'] . '/' . $filename,
1045 'post_mime_type' => $filetype['type'],
1046 'post_title' => preg_replace( '/\.[^.]+$/', '', $filename ),
1047 'post_content' => '',
1048 'post_parent' => 0,
1049 'post_status' => 'inherit'
1050 ),
1051 $new_filepath,
1052 0
1053 );
1054
1055 remove_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
1056
1057 // success?
1058 if ( $thumbnail_id ) {
1059 // make sure that this file is included
1060 require_once( ABSPATH . 'wp-admin/includes/image.php' );
1061
1062 // update database with generated metadata for the attachment
1063 wp_update_attachment_metadata( $thumbnail_id, wp_generate_attachment_metadata( $thumbnail_id, $new_filepath ) );
1064 }
1065 } else
1066 $thumbnail_id = $thumbnail_id[0];
1067 }
1068
1069 return (int) $thumbnail_id;
1070 }
1071
1072 /**
1073 * Change status of new attachment thumbnail replacement.
1074 *
1075 * @param array $data
1076 * @return array
1077 */
1078 function set_attachment_post_status( $data ) {
1079 $data['post_status'] = 'pending';
1080
1081 return $data;
1082 }
1083
1084 /**
1085 * Prepare featured content fields.
1086 *
1087 * @param array $fields
1088 * @return array
1089 */
1090 public function prepare_featured_fields( $fields ) {
1091 foreach ( array( 'post_type', 'post_status', 'post_format', 'post_term', 'post_author', 'page_parent', 'page_template' ) as $option ) {
1092 $fields[$option]['options'] = $this->prepare_query_args( $option );
1093 }
1094
1095 return $fields;
1096 }
1097
1098 /**
1099 * Prepare values option list.
1100 *
1101 * @param string $type
1102 * @return array
1103 */
1104 public function prepare_query_args( $type = '' ) {
1105 $html = '';
1106
1107 switch( $type ) {
1108 case 'post_type':
1109 $data = $this->get_post_types();
1110 break;
1111
1112 case 'post_status':
1113 $data = $this->get_post_statuses();
1114 break;
1115
1116 case 'post_format':
1117 $data = $this->get_post_formats();
1118 break;
1119
1120 case 'post_term':
1121 $taxonomies = $this->get_taxonomies();
1122 $new_terms = [];
1123
1124 if ( ! empty( $taxonomies ) ) {
1125 foreach ( $taxonomies as $tax_id => $label ) {
1126 $terms = get_terms(
1127 array(
1128 'taxonomy' => $tax_id,
1129 'orderby' => 'name',
1130 'order' => 'ASC',
1131 'hide_empty' => false,
1132 'fields' => 'id=>name'
1133 )
1134 );
1135
1136 if ( ! empty( $terms ) )
1137 $new_terms[$tax_id] = array(
1138 'label' => $label,
1139 'terms' => $terms
1140 );
1141 }
1142 }
1143
1144 $data = $new_terms;
1145 break;
1146
1147 case 'post_author':
1148 $data = $this->get_users();
1149 break;
1150
1151 case 'page_parent':
1152 $parents = [];
1153 $hierarchical = get_post_types(
1154 array(
1155 'public' => true,
1156 'hierarchical' => true
1157 ),
1158 'objects',
1159 'and'
1160 );
1161
1162 if ( ! empty( $hierarchical ) ) {
1163 foreach ( $hierarchical as $post_type => $object ) {
1164 // get top level hierarchical posts
1165 $query = new WP_Query(
1166 array(
1167 'post_type' => $post_type,
1168 'post_status' => 'publish',
1169 'nopaging' => true,
1170 'posts_per_page' => -1,
1171 'orderby' => 'title',
1172 'order' => 'ASC',
1173 'suppress_filters' => false,
1174 'no_found_rows' => true,
1175 'cache_results' => false,
1176 'post_parent' => 0
1177 )
1178 );
1179
1180 if ( ! empty( $query->posts ) ) {
1181 foreach ( $query->posts as $post ) {
1182 $parents[$post->ID] = trim( $post->post_title ) === '' ? __( 'Untitled' ) : $post->post_title;
1183 }
1184 }
1185 }
1186 }
1187
1188 $data = $parents;
1189 break;
1190
1191 case 'page_template':
1192 $data = $this->get_page_templates();
1193 break;
1194
1195 default:
1196 $data = [];
1197 }
1198
1199 return apply_filters( 'rl_galleries_prepare_query_args', $data, $type );
1200 }
1201
1202 /**
1203 * Get public post types.
1204 *
1205 * @param bool $simple Which data should be returned
1206 * @param bool $skip Which post types should be skipped
1207 * @return array
1208 */
1209 public function get_post_types( $simple = false, $skip = [ 'attachment', 'rl_gallery' ] ) {
1210 $post_types = get_post_types(
1211 array(
1212 'public' => true
1213 ),
1214 'objects',
1215 'and'
1216 );
1217
1218 $data = [];
1219
1220 if ( ! empty( $post_types ) ) {
1221 foreach ( $post_types as $post_type => $cpt ) {
1222 // skip unwanted post types
1223 if ( in_array( $post_type, $skip, true ) )
1224 continue;
1225
1226 if ( $simple )
1227 $data[] = $post_type;
1228 else
1229 $data[$post_type] = $cpt->labels->singular_name;
1230 }
1231 }
1232
1233 if ( ! $simple )
1234 asort( $data );
1235
1236 return $data;
1237 }
1238
1239 /**
1240 * Get post statuses.
1241 *
1242 * @return array
1243 */
1244 public function get_post_statuses() {
1245 $post_statuses = get_post_stati();
1246
1247 asort( $post_statuses );
1248
1249 // remove inherit post status
1250 if ( isset( $post_statuses['inherit'] ) )
1251 unset( $post_statuses['inherit'] );
1252
1253 return $post_statuses;
1254 }
1255
1256 /**
1257 * Get post formats.
1258 *
1259 * @return array
1260 */
1261 public function get_post_formats() {
1262 $post_formats = array(
1263 'aside' => __( 'Aside' ),
1264 'audio' => __( 'Audio' ),
1265 'chat' => __( 'Chat' ),
1266 'gallery' => __( 'Gallery' ),
1267 'link' => __( 'Link' ),
1268 'photo' => __( 'Photo' ),
1269 'quote' => __( 'Quote' ),
1270 'standard' => __( 'Standard' ),
1271 'status' => __( 'Status' ),
1272 'video' => __( 'Video' )
1273 );
1274
1275 asort( $post_formats );
1276
1277 return $post_formats;
1278 }
1279
1280 /**
1281 * Get taxonomies.
1282 *
1283 * @return array
1284 */
1285 public function get_taxonomies() {
1286 $taxonomies = get_taxonomies(
1287 array(
1288 'public' => true
1289 ),
1290 'objects',
1291 'and'
1292 );
1293
1294 // remove post format
1295 if ( array_key_exists( 'post_format', $taxonomies ) )
1296 unset( $taxonomies['post_format'] );
1297
1298 // get main instance
1299 $rl = Responsive_Lightbox();
1300
1301 // remove gallery categories
1302 if ( $rl->options['builder']['categories'] && array_key_exists( 'rl_category', $taxonomies ) )
1303 unset( $taxonomies['rl_category'] );
1304
1305 // remove gallery tags
1306 if ( $rl->options['builder']['tags'] && array_key_exists( 'rl_tag', $taxonomies ) )
1307 unset( $taxonomies['rl_tag'] );
1308
1309 if ( $rl->options['folders']['active'] ) {
1310 // remove active folders taxonomy from gallery source selector
1311 $active_taxonomy = $rl->folders->get_active_taxonomy();
1312 unset( $taxonomies[$active_taxonomy] );
1313
1314 // remove media folders tags
1315 if ( $rl->options['folders']['media_tags'] )
1316 unset( $taxonomies['rl_media_tag'] );
1317 }
1318
1319 $data = [];
1320
1321 if ( ! empty( $taxonomies ) ) {
1322 foreach ( $taxonomies as $tax_id => $taxonomy ) {
1323 $data[$tax_id] = $taxonomy->labels->singular_name;
1324 }
1325 }
1326
1327 // sort taxonomies
1328 asort( $data );
1329
1330 return $data;
1331 }
1332
1333 /**
1334 * Get users.
1335 *
1336 * @return array
1337 */
1338 public function get_users() {
1339 $users = get_users(
1340 array(
1341 'fields' => array( 'ID', 'user_login' )
1342 )
1343 );
1344
1345 $data = [];
1346
1347 if ( ! empty( $users ) ) {
1348 foreach ( $users as $user ) {
1349 $data[(int) $user->ID] = $user->user_login;
1350 }
1351 }
1352
1353 asort( $data );
1354
1355 return $data;
1356 }
1357
1358 /**
1359 * Get page templates.
1360 *
1361 * @return array
1362 */
1363 public function get_page_templates() {
1364 $data = [];
1365 $page_templates = wp_get_theme()->get_page_templates();
1366
1367 if ( ! empty( $page_templates ) )
1368 asort( $page_templates );
1369
1370 $data = array_merge( array( 'default' => apply_filters( 'default_page_template_title', __( 'Default Template' ) ) ), $page_templates );
1371
1372 return $data;
1373 }
1374
1375 /**
1376 * Fix possible misplaced or hidden metaboxes do to old 'after_title' metabox and possibility to move internal metaboxes.
1377 *
1378 * @return void
1379 */
1380 public function clear_metaboxes( $screen ) {
1381 global $pagenow;
1382
1383 if ( ! ( ( $pagenow === 'post.php' || $pagenow === 'post-new.php' ) && ! empty( $screen->post_type ) && $screen->post_type === 'rl_gallery' && empty( $_POST['rl_gallery'] ) ) )
1384 return;
1385
1386 // get user id
1387 $user_id = get_current_user_id();
1388
1389 // get rl metaboxes
1390 $order = get_user_meta( $user_id, 'meta-box-order_rl_gallery', true );
1391
1392 // any metabox order? fix possible misplaced metaboxes
1393 if ( is_array( $order ) && ! empty( $order ) ) {
1394 // save metaboxes
1395 $_order = $order;
1396
1397 // default rl metaboxes
1398 $rl_boxes = [ 'responsive-gallery-images', 'responsive-gallery-config', 'responsive-gallery-design', 'responsive-gallery-paging', 'responsive-gallery-lightbox', 'responsive-gallery-misc' ];
1399
1400 foreach ( $_order as $group => $metaboxes ) {
1401 if ( $group === 'after_title' ) {
1402 // remove deprecated after_title metabox
1403 unset( $order['after_title'] );
1404 } elseif ( $metaboxes !== '' ) {
1405 $boxes = explode( ',', $metaboxes );
1406 $new_boxes = [];
1407
1408 foreach ( $boxes as $box ) {
1409 if ( ! in_array( $box, $rl_boxes, true ) )
1410 $new_boxes[] = $box;
1411 }
1412
1413 if ( ! empty( $new_boxes ) )
1414 $order[$group] = implode( ',', $new_boxes );
1415 else
1416 $order[$group] = '';
1417 }
1418 }
1419
1420 // remove default metaboxes storage
1421 if ( array_key_exists( 'responsive_lightbox_metaboxes', $order ) )
1422 unset( $order['responsive_lightbox_metaboxes'] );
1423
1424 // update usermeta to prevent issues with rl metaboxes
1425 if ( $order !== $_order )
1426 update_user_meta( $user_id, 'meta-box-order_rl_gallery', $order );
1427 }
1428 }
1429
1430 /**
1431 * Save gallery metadata.
1432 *
1433 * @param int $post_id
1434 * @param object $post
1435 * @param bool $update Whether existing post is being updated or not
1436 * @return void
1437 */
1438 public function save_post( $post_id, $post, $update ) {
1439 // check action
1440 $action = isset( $_GET['action'] ) ? sanitize_key( $_GET['action'] ) : '';
1441
1442 if ( wp_is_post_revision( $post_id ) || ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || ! $update || in_array( $post->post_status, array( 'trash', 'auto-draft' ), true ) || ( $action === 'untrash' ) || empty( $_POST['rl_gallery'] ) )
1443 return;
1444
1445 // save gallery
1446 $this->save_gallery( wp_unslash( $_POST ), $post_id );
1447 }
1448
1449 /**
1450 * Save gallery preview metadata.
1451 *
1452 * @param array $post_data Gallery data
1453 * @param int $post_id
1454 * @param bool $preview Whether is it preview
1455 * @return void
1456 */
1457 public function save_gallery( $post_data, $post_id, $preview = false ) {
1458 // get gallery data
1459 $data = $post_data['rl_gallery'];
1460
1461 // prepare sanitized data
1462 $safedata = [];
1463
1464 // get main instance
1465 $rl = Responsive_Lightbox();
1466
1467 // sanitize all fields - iterate from $this->tabs (authoritative registry) to prevent silent skipping
1468 foreach ( array_keys( $this->tabs ) as $tab_id ) {
1469 // Retrieve menu_items from $this->fields for this tab (may be empty for adapter-only tabs)
1470 $menu_items = isset( $this->fields[$tab_id] ) ? $this->fields[$tab_id] : [];
1471
1472 // Determine menu item for this tab
1473 $tab_menu_items = isset( $this->tabs[$tab_id]['menu_items'] ) && is_array( $this->tabs[$tab_id]['menu_items'] ) ? $this->tabs[$tab_id]['menu_items'] : [];
1474 $posted_menu_item = isset( $data[$tab_id], $data[$tab_id]['menu_item'] ) ? sanitize_key( $data[$tab_id]['menu_item'] ) : '';
1475
1476 // Resolve menu item safely for tabs with and without menu navigation.
1477 if ( $posted_menu_item !== '' ) {
1478 if ( ! empty( $tab_menu_items ) && array_key_exists( $posted_menu_item, $tab_menu_items ) )
1479 $menu_item = $posted_menu_item;
1480 elseif ( array_key_exists( $posted_menu_item, $menu_items ) )
1481 $menu_item = $posted_menu_item;
1482 else {
1483 if ( empty( $menu_items ) )
1484 continue;
1485 $menu_item = array_key_exists( 'options', $menu_items ) ? 'options' : key( $menu_items );
1486 }
1487 } else {
1488 if ( empty( $menu_items ) )
1489 continue;
1490 $menu_item = array_key_exists( 'options', $menu_items ) ? 'options' : key( $menu_items );
1491 }
1492
1493 // Resolve fields from adapter (single source for managed tabs)
1494 $items = [];
1495 if ( isset( $rl->gallery_api ) && $rl->gallery_api->is_managed_tab( $tab_id ) ) {
1496 $items = $rl->gallery_api->get_tab_fields_for_save( $tab_id, $menu_item );
1497 }
1498
1499 // Defensive fallback for images tab only (not fully adapter-owned for field definitions)
1500 if ( $tab_id === 'images' && empty( $items ) && isset( $menu_items[$menu_item] ) && is_array( $menu_items[$menu_item] ) ) {
1501 $items = $menu_items[$menu_item];
1502 }
1503
1504 if ( empty( $items ) || ! is_array( $items ) )
1505 continue;
1506
1507 // IMAGES TAB: Minimal defensive guards (sanitizer handles data structure)
1508 if ( $tab_id === 'images' ) {
1509 // Ensure folder field has valid structure for folders menu item
1510 if ( $menu_item === 'folders' && isset( $data[$tab_id][$menu_item]['folder'] ) ) {
1511 $folder = $data[$tab_id][$menu_item]['folder'];
1512 if ( ! is_array( $folder ) ) {
1513 $data[$tab_id][$menu_item]['folder'] = [ 'id' => 0, 'children' => false ];
1514 } else {
1515 if ( ! isset( $folder['id'] ) ) {
1516 $data[$tab_id][$menu_item]['folder']['id'] = 0;
1517 }
1518 if ( ! isset( $folder['children'] ) ) {
1519 $data[$tab_id][$menu_item]['folder']['children'] = false;
1520 }
1521 }
1522 }
1523 // Note: attachments['ids'] is CSV string, sanitizer handles it at line 1997
1524 }
1525
1526 // sanitize fields
1527 $safedata = $this->sanitize_fields( $items, $data, $tab_id, $menu_item );
1528
1529 // tab validation hook (adapter-managed tabs)
1530 if ( isset( $rl->gallery_api ) && $rl->gallery_api->is_managed_tab( $tab_id ) ) {
1531 if ( isset( $safedata[$tab_id][$menu_item] ) && is_array( $safedata[$tab_id][$menu_item] ) ) {
1532 $safedata[$tab_id][$menu_item] = $rl->gallery_api->validate_tab_data(
1533 $tab_id,
1534 $menu_item,
1535 $safedata[$tab_id][$menu_item],
1536 $post_id
1537 );
1538 }
1539 }
1540
1541 // add menu item
1542 $safedata[$tab_id]['menu_item'] = $menu_item;
1543
1544 // preview?
1545 if ( $preview )
1546 update_metadata( 'post', $post_id, '_rl_' . $tab_id, $safedata[$tab_id] );
1547 else
1548 update_post_meta( $post_id, '_rl_' . $tab_id, $safedata[$tab_id] );
1549 }
1550
1551 $has_featured_image_payload = isset( $post_data['rl_gallery_featured_image'] );
1552
1553 // Preserve existing featured-image metadata for partial updates (e.g. Quick Edit).
1554 if ( ! $has_featured_image_payload ) {
1555 $featured_image_type = get_post_meta( $post_id, '_rl_featured_image_type', true );
1556 $featured_image = get_post_meta( $post_id, '_rl_featured_image', true );
1557 $thumbnail_id = (int) get_post_meta( $post_id, '_thumbnail_id', true );
1558
1559 if ( ! in_array( $featured_image_type, [ 'id', 'url', 'image' ], true ) )
1560 $featured_image_type = 'image';
1561 } else {
1562 $featured_image_type = ! empty( $post_data['rl_gallery_featured_image'] ) && in_array( $post_data['rl_gallery_featured_image'], array( 'id', 'url', 'image' ), true ) ? $post_data['rl_gallery_featured_image'] : 'id';
1563
1564 switch ( $featured_image_type ) {
1565 // custom url
1566 case 'url':
1567 $thumbnail_id = $this->maybe_generate_thumbnail();
1568 $frontend = function_exists( 'Responsive_Lightbox' ) ? Responsive_Lightbox()->frontend : null;
1569 $custom_url = isset( $post_data['_rl_thumbnail_url'] ) ? $post_data['_rl_thumbnail_url'] : '';
1570 if ( $frontend && method_exists( $frontend, 'sanitize_remote_image_url' ) )
1571 $featured_image = $frontend->sanitize_remote_image_url( $custom_url );
1572 else
1573 $featured_image = '';
1574
1575 if ( $featured_image === '' )
1576 $featured_image_type = 'image';
1577 break;
1578
1579 // first image
1580 case 'image':
1581 $thumbnail_id = $this->maybe_generate_thumbnail();
1582 $featured_image = '';
1583 break;
1584
1585 // attachment id
1586 case 'id':
1587 default:
1588 $featured_image = $thumbnail_id = isset( $post_data['_thumbnail_id'] ) ? (int) $post_data['_thumbnail_id'] : 0;
1589 }
1590 }
1591
1592 // preview?
1593 if ( $preview ) {
1594 update_metadata( 'post', $post_id, '_rl_featured_image_type', $featured_image_type );
1595 update_metadata( 'post', $post_id, '_rl_featured_image', $featured_image );
1596 update_metadata( 'post', $post_id, '_thumbnail_id', $thumbnail_id );
1597 } else {
1598 // update featured image
1599 update_post_meta( $post_id, '_rl_featured_image_type', $featured_image_type );
1600 update_post_meta( $post_id, '_rl_featured_image', $featured_image );
1601 update_post_meta( $post_id, '_thumbnail_id', $thumbnail_id );
1602
1603 // save number of images
1604 update_post_meta( $post_id, '_rl_images_count', $this->get_gallery_images_number( $post_id ) );
1605 }
1606
1607 // update post excerpt
1608 if ( isset( $safedata['misc']['options']['gallery_description'] ) ) {
1609 remove_action( 'save_post_rl_gallery', [ $this, 'save_post' ], 10, 3 );
1610
1611 $postdata = [
1612 'ID' => $post_id,
1613 'post_excerpt' => sanitize_textarea_field( $safedata['misc']['options']['gallery_description'] )
1614 ];
1615
1616 wp_update_post( $postdata );
1617
1618 add_action( 'save_post_rl_gallery', [ $this, 'save_post' ], 10, 3 );
1619 }
1620 }
1621
1622 /**
1623 * Display shortcode metabox.
1624 *
1625 * @param object $post
1626 * @return void
1627 */
1628 public function shortcode_metabox( $post ) {
1629 echo '
1630 <p>' . esc_html__( 'You can place this gallery anywhere into your posts, pages, custom post types or widgets by using the shortcode below', 'responsive-lightbox' ) . ':</p>
1631 <code class="rl-shortcode" data-number="0">[rl_gallery id=&quot;' . (int) $post->ID . '&quot;]</code>
1632 <p>' . esc_html__( 'You can also place this gallery into your template files by using the template tag below', 'responsive-lightbox' ) . ':</p>
1633 <code class="rl-shortcode" data-number="1">if ( function_exists( \'rl_gallery\' ) ) { rl_gallery( \'' . (int) $post->ID . '\' ); }</code>';
1634 }
1635
1636 /**
1637 * Add new gallery listing columns.
1638 *
1639 * @param array $columns
1640 * @return array
1641 */
1642 public function gallery_columns( $columns ) {
1643 // find title position
1644 $offset = array_search( 'title', array_keys( $columns ) );
1645
1646 // put image column before title
1647 $columns = array_merge(
1648 array_slice( $columns, 0, $offset ),
1649 array(
1650 'image' => esc_html__( 'Gallery', 'responsive-lightbox' )
1651 ),
1652 array_slice( $columns, $offset )
1653 );
1654
1655 // put new columns after title
1656 $columns = array_merge(
1657 array_slice( $columns, 0, $offset + 2 ),
1658 array(
1659 'shortcode' => esc_html__( 'Shortcode', 'responsive-lightbox' ),
1660 'type' => esc_html__( 'Type', 'responsive-lightbox' ),
1661 'source' => esc_html__( 'Source', 'responsive-lightbox' )
1662 ),
1663 array_slice( $columns, $offset + 2 )
1664 );
1665
1666 return $columns;
1667 }
1668
1669 /**
1670 * Add new gallery listing columns content.
1671 *
1672 * @global string $pagenow
1673 *
1674 * @param string $column_name
1675 * @param int $post_id
1676 * @return void
1677 */
1678 public function gallery_columns_content( $column_name, $post_id ) {
1679 switch ( $column_name ) {
1680 case 'image':
1681 // get image data, based on gallery source type
1682 $image = $this->get_featured_image( $post_id, 'thumbnail' );
1683 $images_count = (int) get_post_meta( $post_id, '_rl_images_count', true );
1684
1685 // display count
1686 if ( ! empty( $image ) )
1687 echo '<span class="media-icon image-icon">' . wp_kses_post( $image ) . '</span><span>' . esc_html( sprintf( _n( '%s element', '%s elements', $images_count, 'responsive-lightbox' ), $images_count ) ) . '</span>';
1688 else
1689 echo '<span class="media-icon image-icon">' . wp_get_attachment_image( 0, array( 60, 60 ), true, array( 'alt' => '' ) ) . '</span>';
1690 break;
1691
1692 case 'shortcode':
1693 echo '<code>[rl_gallery id="' . (int) $post_id . '"]</code>';
1694 break;
1695
1696 case 'type':
1697 $config = get_post_meta( $post_id, '_rl_config', true );
1698
1699 if ( ! empty( $config['menu_item'] ) && array_key_exists( $config['menu_item'], $this->tabs['config']['menu_items'] ) ) {
1700 echo esc_html( $this->tabs['config']['menu_items'][$config['menu_item']] );
1701
1702 if ( $config['menu_item'] === 'default' )
1703 echo esc_html( ' (' . $this->tabs['config']['menu_items'][Responsive_Lightbox()->options['settings']['builder_gallery']] . ')' );
1704 } else
1705 echo '-';
1706 break;
1707
1708 case 'source':
1709 $images = get_post_meta( $post_id, '_rl_images', true );
1710
1711 if ( ! empty( $images['menu_item'] ) && array_key_exists( $images['menu_item'], $this->tabs['images']['menu_items'] ) )
1712 echo esc_html( $this->tabs['images']['menu_items'][$images['menu_item']] );
1713 else
1714 echo '-';
1715 break;
1716 }
1717 }
1718
1719 /**
1720 * Get size information for all currently-registered image sizes.
1721 *
1722 * @global array $_wp_additional_image_sizes
1723 *
1724 * @return array
1725 */
1726 public function get_image_sizes() {
1727 global $_wp_additional_image_sizes;
1728
1729 $sizes = [];
1730
1731 foreach ( get_intermediate_image_sizes() as $_size ) {
1732 if ( in_array( $_size, [ 'thumbnail', 'medium', 'medium_large', 'large' ] ) ) {
1733 $sizes[$_size]['width'] = get_option( "{$_size}_size_w" );
1734 $sizes[$_size]['height'] = get_option( "{$_size}_size_h" );
1735 $sizes[$_size]['crop'] = (bool) get_option( "{$_size}_crop" );
1736 } elseif ( isset( $_wp_additional_image_sizes[$_size] ) ) {
1737 $sizes[$_size] = [
1738 'width' => $_wp_additional_image_sizes[$_size]['width'],
1739 'height' => $_wp_additional_image_sizes[$_size]['height'],
1740 'crop' => $_wp_additional_image_sizes[$_size]['crop'],
1741 ];
1742 }
1743 }
1744
1745 return $sizes;
1746 }
1747
1748 /**
1749 * Get size information for a specific image size.
1750 *
1751 * @param string $size The image size for which to retrieve data.
1752 * @return false|array
1753 */
1754 public function get_image_size( $size ) {
1755 if ( isset( $this->sizes[$size] ) )
1756 return $this->sizes[$size];
1757 else
1758 return false;
1759 }
1760
1761 /**
1762 * Filter the admin post thumbnail HTML markup.
1763 *
1764 * @param string $content
1765 * @param int $post_id
1766 * @param int $thumbnail_id
1767 * @return string
1768 */
1769 public function admin_post_thumbnail_html( $content, $post_id, $thumbnail_id ) {
1770 if ( get_post_type( $post_id ) === 'rl_gallery' ) {
1771 $value = get_post_meta( $post_id, '_rl_featured_image', true );
1772 $frontend = function_exists( 'Responsive_Lightbox' ) ? Responsive_Lightbox()->frontend : null;
1773 if ( $frontend && method_exists( $frontend, 'sanitize_remote_image_url' ) )
1774 $value = $frontend->sanitize_remote_image_url( $value );
1775 $type = get_post_meta( $post_id, '_rl_featured_image_type', true );
1776 $type = ! empty( $type ) && in_array( $type, array( 'image', 'id', 'url' ) ) ? $type : 'image';
1777
1778 // force media library image
1779 if ( wp_doing_ajax() )
1780 $type = 'id';
1781 // post featured image is post thumbnail replacement?
1782 elseif ( $this->maybe_generate_thumbnail() === (int) $thumbnail_id ) {
1783 remove_filter( 'admin_post_thumbnail_html', array( $this, 'admin_post_thumbnail_html' ), 10 );
1784
1785 $content = _wp_post_thumbnail_html( 0, $post_id );
1786 }
1787
1788 $content = '
1789 <div class="rl-gallery-featured-image-options">
1790 <p class="howto">' . esc_html__( 'Select gallery featured image source:', 'responsive-lightbox' ) . '</p>
1791 <label for="rl-gallery-featured-image"><input id="rl-gallery-featured-image" type="radio" name="rl_gallery_featured_image" value="image" ' . checked( $type, 'image', false ) . ' />' . esc_html__( 'First gallery image', 'responsive-lightbox' ) . '</label><br />
1792 <label for="rl-gallery-featured-id"><input id="rl-gallery-featured-id" type="radio" name="rl_gallery_featured_image" value="id" ' . checked( $type, 'id', false ) . ' />' . esc_html__( 'Media Library', 'responsive-lightbox' ) . '</label><br />
1793 <label for="rl-gallery-featured-url"><input id="rl-gallery-featured-url" type="radio" name="rl_gallery_featured_image" value="url" ' . checked( $type, 'url', false ) . ' />' . esc_html__( 'Custom URL', 'responsive-lightbox' ) . '</label>
1794 </div>
1795 <div class="rl-gallery-featured-image-select">
1796 <div class="rl-gallery-featured-image-select-id"' . ( $type === 'id' ? '' : ' style="display: none;"' ) . '>' . $content . '</div>
1797 <div class="rl-gallery-featured-image-select-url"' . ( $type === 'url' ? '' : ' style="display: none;"' ) . '>
1798 <p><input id="_rl_thumbnail_url" class="large-text" name="_rl_thumbnail_url" value="' . ( $type === 'url' ? esc_url( $value ) : '' ) . '" type="text" /></p>
1799 <p class="howto">' . esc_html__( 'Custom featured image URL', 'responsive-lightbox' ) . '</p>
1800 </div>
1801 <div class="rl-gallery-featured-image-select-image"' . ( $type === 'image' ? '' : ' style="display: none;"' ) . '><p class="howto">' . esc_html__( 'Dynamically generated first gallery image', 'responsive-lightbox' ) . '</p></div>
1802 </div>
1803 ';
1804 }
1805
1806 return $content;
1807 }
1808
1809 /**
1810 * Modify the resulting HTML so that the feature image is set as a background property.
1811 *
1812 * @param string $html The HTML image tag.
1813 * @param int $post_id The post whose featured image is to be printed.
1814 * @param int $post_thumbnail_id The post thumbnail ID.
1815 * @param array|string $size The size of the featured image.
1816 * @param array $attr Additional attributes.
1817 * @return string
1818 */
1819 public function post_thumbnail_html( $html, $post_id = 0, $post_thumbnail_id = 0, $size = false, $attr = [] ) {
1820 if ( get_post_type( $post_id ) === 'rl_gallery' ) {
1821 // get featured image type
1822 $image_type = get_post_meta( $post_id, '_rl_featured_image_type', true );
1823
1824 // break if featured image type is media library
1825 if ( ! $image_type || $image_type == 'id' )
1826 return $html;
1827
1828 // get image source
1829 $image_src = $this->get_gallery_image_src( $this->get_featured_image_src( $post_id ) );
1830
1831 // no image?
1832 if ( empty( $image_src ) )
1833 return $html;
1834
1835 // add featured image as background in style tag
1836 $style = 'style="background:url( ' . esc_url( $image_src['url'] ) . ' ) no-repeat center center;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size: cover;"';
1837
1838 $html = str_replace( 'src=', $style . ' src=', $html );
1839
1840 // fix the alt tag (if possible)
1841 $alt = $image_src['alt'];
1842
1843 if ( isset( $attr['alt'] ) )
1844 $alt = $attr['alt'];
1845
1846 if ( $alt ) {
1847 $html = str_replace( '/(alt=\'[^\']+\'\|alt="[^"]+")/', '', $html );
1848 $html = str_replace( 'src=', ' alt="' . esc_attr( $alt ) . '" src=', $html );
1849 }
1850 }
1851
1852 return $html;
1853 }
1854 }
1855
1856